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

Update 2.5-branch with relevant 2.4-branch cherry-picks #344

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
30 changes: 19 additions & 11 deletions src/app/chip_data_model.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ endfunction()
#
# Configure ${APP_TARGET} with source files associated with clusters enabled in the ${ZAP_FILE}
#
function(chip_configure_zap_file APP_TARGET ZAP_FILE)
function(chip_configure_zap_file APP_TARGET ZAP_FILE EXTERNAL_CLUSTERS)
find_package(Python3 REQUIRED)
set(args --zap_file ${ZAP_FILE})

if (EXTERNAL_CLUSTERS)
list(APPEND args --external-clusters ${EXTERNAL_CLUSTERS})
endif()

execute_process(
COMMAND ${Python3_EXECUTABLE} ${CHIP_APP_BASE_DIR}/zap_cluster_list.py --zap_file ${ZAP_FILE}
COMMAND ${Python3_EXECUTABLE} ${CHIP_APP_BASE_DIR}/zap_cluster_list.py ${args}
OUTPUT_VARIABLE CLUSTER_LIST
ERROR_VARIABLE ERROR_MESSAGE
RESULT_VARIABLE RC
Expand All @@ -54,18 +59,21 @@ endfunction()
#
# Configure ${APP_TARGET} based on the selected data model configuration.
# Available options are:
# SCOPE Cmake scope keyword that defines the scope of included sources
# The default is PRIVATE scope.
# INCLUDE_SERVER Include source files from src/app/server directory
# SCOPE CMake scope keyword that defines the scope of included sources.
# The default is PRIVATE scope.
# INCLUDE_SERVER Include source files from src/app/server directory.
# BYPASS_IDL Bypass code generation from .matter IDL file.
# ZAP_FILE Path to the ZAP file, used to determine the list of clusters
# supported by the application.
# IDL .matter IDL file to use for codegen. Inferred from ZAP_FILE
# if not provided
# ZAP_FILE Path to the ZAP file, used to determine the list of clusters
# supported by the application.
# IDL .matter IDL file to use for codegen. Inferred from ZAP_FILE
# if not provided
# EXTERNAL_CLUSTERS Clusters with external implementations. The default implementations
# will not be used nor required for these clusters.
# Format: MY_CUSTOM_CLUSTER'.
#
function(chip_configure_data_model APP_TARGET)
set(SCOPE PRIVATE)
cmake_parse_arguments(ARG "INCLUDE_SERVER;BYPASS_IDL" "ZAP_FILE;GEN_DIR;IDL" "" ${ARGN})
cmake_parse_arguments(ARG "INCLUDE_SERVER;BYPASS_IDL" "SCOPE;ZAP_FILE;GEN_DIR;IDL" "EXTERNAL_CLUSTERS" ${ARGN})

if (ARG_SCOPE)
set(SCOPE ${ARG_SCOPE})
Expand All @@ -88,7 +96,7 @@ function(chip_configure_data_model APP_TARGET)
endif()

if (ARG_ZAP_FILE)
chip_configure_zap_file(${APP_TARGET} ${ARG_ZAP_FILE})
chip_configure_zap_file(${APP_TARGET} ${ARG_ZAP_FILE} "${ARG_EXTERNAL_CLUSTERS}")
if (NOT ARG_IDL)
string(REPLACE ".zap" ".matter" ARG_IDL ${ARG_ZAP_FILE})
endif()
Expand Down
28 changes: 6 additions & 22 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ template("chip_data_model") {
"*",
[
"zap_pregenerated_dir",
"zap_clusters_with_custom_implementation",
"zap_file",
"is_server",
"external_clusters",
])

if (!defined(sources)) {
Expand Down Expand Up @@ -194,34 +194,18 @@ template("chip_data_model") {
_script_path = rebase_path(_zap_cluster_list_script, root_build_dir)
_script_args = [ "--zap_file=" + _zap_path ]

if (defined(invoker.external_clusters)) {
_script_args += [ "--external-clusters" ]
_script_args += invoker.external_clusters
}
_cluster_sources = exec_script("${build_root}/gn_run_binary.py",
[ _script_path ] + _script_args,
"list lines",
[ invoker.zap_file ])
}

_custom_impl_clusters = []
if (defined(invoker.zap_clusters_with_custom_implementation)) {
_custom_impl_clusters = invoker.zap_clusters_with_custom_implementation
}

if (_cluster_sources == []) {
# The variable is only used within the nested foreach-loop and will be
# unused before it goes out of scope when the outter-loop is not entered.
not_needed([ "_custom_impl_clusters" ])
}

foreach(cluster, _cluster_sources) {
_custom_impl = false
foreach(ci, _custom_impl_clusters) {
if (cluster == ci) {
_custom_impl = true
}
}

if (_custom_impl) {
# do not include any sources, we have a custom implementation for this cluster
} else if (cluster == "door-lock-server") {
if (cluster == "door-lock-server") {
sources += [
"${_app_root}/clusters/${cluster}/door-lock-server-callback.cpp",
"${_app_root}/clusters/${cluster}/door-lock-server.cpp",
Expand Down
24 changes: 21 additions & 3 deletions src/app/clusters/door-lock-server/door-lock-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,18 @@ bool DoorLockServer::SetPrivacyModeButton(chip::EndpointId endpointId, bool isEn
return SetAttribute(endpointId, Attributes::EnablePrivacyModeButton::Id, Attributes::EnablePrivacyModeButton::Set, isEnabled);
}

void DoorLockServer::HandleLocalLockOperationError(chip::EndpointId endpointId, LockOperationTypeEnum opType,
OperationSourceEnum opSource, Nullable<uint16_t> userId)
{
SendLockOperationEvent(endpointId, opType, opSource, OperationErrorEnum::kInvalidCredential, userId,
Nullable<chip::FabricIndex>(), Nullable<chip::NodeId>(), Nullable<List<const LockOpCredentials>>(),
false);

HandleWrongCodeEntry(endpointId);

ChipLogProgress(Zcl, "Handling a local Lock Operation Error: [endpoint=%d, user=%d]", endpointId, userId.Value());
}

bool DoorLockServer::HandleWrongCodeEntry(chip::EndpointId endpointId)
{
auto endpointContext = getContext(endpointId);
Expand Down Expand Up @@ -1330,12 +1342,13 @@ bool DoorLockServer::OnFabricRemoved(chip::EndpointId endpointId, chip::FabricIn
"[OnFabricRemoved] Handling a fabric removal from the door lock server [endpointId=%d,fabricIndex=%d]", endpointId,
fabricIndex);

bool status{ true };
// Iterate over all the users and clean up the deleted fabric
if (!clearFabricFromUsers(endpointId, fabricIndex))
{
ChipLogError(Zcl, "[OnFabricRemoved] Unable to cleanup fabric from users - internal error [endpointId=%d,fabricIndex=%d]",
endpointId, fabricIndex);
return false;
status = false;
}

// Iterate over all the credentials and clean up the fabrics
Expand All @@ -1344,10 +1357,15 @@ bool DoorLockServer::OnFabricRemoved(chip::EndpointId endpointId, chip::FabricIn
ChipLogError(Zcl,
"[OnFabricRemoved] Unable to cleanup fabric from credentials - internal error [endpointId=%d,fabricIndex=%d]",
endpointId, fabricIndex);
return false;
status = false;
}

return true;
if (mOnFabricRemovedCustomCallback)
{
mOnFabricRemovedCustomCallback(endpointId, fabricIndex);
}

return status;
}

/**********************************************************
Expand Down
29 changes: 29 additions & 0 deletions src/app/clusters/door-lock-server/door-lock-server.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class DoorLockServer
public:
static DoorLockServer & Instance();

using OnFabricRemovedCustomCallback = void (*)(chip::EndpointId endpointId, chip::FabricIndex fabricIndex);

void InitServer(chip::EndpointId endpointId);

/**
Expand Down Expand Up @@ -188,6 +190,17 @@ class DoorLockServer
return GetFeatures(endpointId).Has(DoorLockFeature::kUser) && SupportsAnyCredential(endpointId);
}

/**
* @brief Allows the application to register a custom callback which will be called after the default DoorLock
* OnFabricRemoved implementation.
*
* @param callback callback to be registered
*/
inline void SetOnFabricRemovedCustomCallback(OnFabricRemovedCustomCallback callback)
{
mOnFabricRemovedCustomCallback = callback;
}

bool OnFabricRemoved(chip::EndpointId endpointId, chip::FabricIndex fabricIndex);

static void DoorLockOnAutoRelockCallback(chip::System::Layer *, void * callbackContext);
Expand All @@ -201,6 +214,20 @@ class DoorLockServer
*/
void ResetWrongCodeEntryAttempts(chip::EndpointId endpointId);

/**
* @brief Handles a local lock operation error. This method allows handling a wrong attempt of providing
* user credential entry that has been provided locally by the user. The method will emit the LockOperationEvent
* to inform the controller that a local wrong attempt occurred, and also call HandleWrongEntry method to
* increment wrong entry counter.
*
* @param endpointId
* @param opType Operation source to be registered in the LockOperationEvent.
* @param opSource source of the operation to be registered in the LockOperationEvent.
* @param userId Optional user id to be registered in the LockOperationEvent
*/
void HandleLocalLockOperationError(chip::EndpointId endpointId, LockOperationTypeEnum opType, OperationSourceEnum opSource,
Nullable<uint16_t> userId);

private:
chip::FabricIndex getFabricIndex(const chip::app::CommandHandler * commandObj);
chip::NodeId getNodeId(const chip::app::CommandHandler * commandObj);
Expand Down Expand Up @@ -558,6 +585,8 @@ class DoorLockServer

std::array<EmberAfDoorLockEndpointContext, EMBER_AF_DOOR_LOCK_CLUSTER_SERVER_ENDPOINT_COUNT> mEndpointCtx;

OnFabricRemovedCustomCallback mOnFabricRemovedCustomCallback{ nullptr };

static DoorLockServer instance;
};

Expand Down
15 changes: 13 additions & 2 deletions src/app/zap_cluster_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ def get_cluster_sources(clusters: typing.Set[str],
return cluster_sources


def dump_zapfile_clusters(zap_file_path: pathlib.Path, implementation_data_path: pathlib.Path):
def dump_zapfile_clusters(zap_file_path: pathlib.Path,
implementation_data_path: pathlib.Path,
external_clusters: typing.List[str]):
"""Prints all of the source directories to build for a given ZAP file.

Arguments:
Expand All @@ -56,6 +58,8 @@ def dump_zapfile_clusters(zap_file_path: pathlib.Path, implementation_data_path:

for endpoint_type in zap_json.get('endpointTypes'):
for cluster in endpoint_type.get('clusters'):
if cluster.get('define') in external_clusters:
continue
side: str = cluster.get('side')
if side == 'client':
clusters_set = client_clusters
Expand Down Expand Up @@ -90,10 +94,17 @@ def main():
required=False,
type=pathlib.Path,
default=os.path.join(os.path.dirname(__file__), "zap_cluster_list.json"))
parser.add_argument('--external-clusters',
help='Clusters with external implementations. ' +
'The default implementations will not be used nor required for these clusters. ' +
'Format: MY_CUSTOM_CLUSTER',
nargs='+',
metavar='EXTERNAL_CLUSTER',
default=[])

args = parser.parse_args()

dump_zapfile_clusters(args.zap_file, args.cluster_implementation_data)
dump_zapfile_clusters(args.zap_file, args.cluster_implementation_data, args.external_clusters)

sys.exit(0)

Expand Down
Loading