Skip to content

Commit 37d4238

Browse files
committed
GH-43: Credential Set Error Report Command Support
Bug-SiliconLabs: UIC-3222 Bug-GitHub: #43
1 parent c4a5219 commit 37d4238

File tree

2 files changed

+482
-0
lines changed

2 files changed

+482
-0
lines changed

applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.cpp

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,11 @@ user_credential_user_unique_id_t get_user_id(const uint8_t *event_parameters)
10071007
{
10081008
return get_uint16_value(event_parameters, INDEX_USER_UNIQUE_ID);
10091009
}
1010+
user_credential_modifier_type_t get_credential_modifier_type(const uint8_t *event_parameters)
1011+
{
1012+
// TODO : Update this with the new specification where CREDENTIAL_DATA doesn't exists anymore
1013+
return event_parameters[8];
1014+
}
10101015

10111016
attribute_store_node_t
10121017
get_credential_type_node(attribute_store_node_t endpoint_node,
@@ -1441,6 +1446,50 @@ void on_notification_event(attribute_store_node_t endpoint_node,
14411446
credential_slot,
14421447
user_id);
14431448
} break;
1449+
// Credential unchanged
1450+
case 0x2E: {
1451+
sl_log_debug(LOG_TAG, "Notification : Credential Unchanged");
1452+
if (!notification_handler::credential::is_report_size_conform(
1453+
event_parameters_length)) {
1454+
return;
1455+
}
1456+
1457+
// Used in logs
1458+
user_credential_type_t credential_type
1459+
= notification_handler::credential::get_credential_type(
1460+
event_parameters);
1461+
user_credential_slot_t credential_slot
1462+
= notification_handler::credential::get_credential_slot(
1463+
event_parameters);
1464+
user_credential_user_unique_id_t user_id
1465+
= notification_handler::credential::get_user_id(event_parameters);
1466+
1467+
// Type and slot
1468+
auto credential_slot_node = get_credential_slot_node_by_type();
1469+
if (credential_slot_node == ATTRIBUTE_STORE_INVALID_NODE) {
1470+
return;
1471+
}
1472+
1473+
// If user doesn't exists in the device we try to remove it also from our side
1474+
user_credential_modifier_type_t modifier_type
1475+
= notification_handler::credential::get_credential_modifier_type(event_parameters);
1476+
if (modifier_type == CREDENTIAL_REPORT_DNE) {
1477+
attribute_store_delete_node(credential_slot_node);
1478+
} else {
1479+
sl_log_info(LOG_TAG,
1480+
"Credential Unchanged, clearing desired values. For Type "
1481+
"%d, Slot %d (User %d)",
1482+
credential_type,
1483+
credential_slot,
1484+
user_id);
1485+
1486+
attribute_store_undefine_desired(credential_slot_node);
1487+
attribute_store_undefine_desired(
1488+
attribute_store_get_node_child_by_type(credential_slot_node,
1489+
ATTRIBUTE(CREDENTIAL_DATA),
1490+
0));
1491+
}
1492+
} break;
14441493
default:
14451494
break;
14461495
}
@@ -2129,6 +2178,19 @@ sl_status_t zwave_command_class_user_credential_credential_handle_report(
21292178
return SL_STATUS_NOT_SUPPORTED;
21302179
}
21312180

2181+
// Remove node if it doesn't exist anymore on the end device
2182+
if (frame_data[INDEX_CREDENTIAL_MODIFIER_TYPE] == CREDENTIAL_REPORT_DNE) {
2183+
sl_log_info(
2184+
LOG_TAG,
2185+
"Credential Node %d (credential type %d, user %d) doesn't exist "
2186+
"anymore, removing it",
2187+
credential_slot,
2188+
credential_type,
2189+
user_id);
2190+
attribute_store_delete_node(credential_slot_node);
2191+
return SL_STATUS_OK;
2192+
}
2193+
21322194
// Update credential slot node & type
21332195
attribute_store_set_reported(credential_type_node,
21342196
&credential_type,
@@ -2202,6 +2264,123 @@ sl_status_t zwave_command_class_user_credential_credential_handle_report(
22022264
return SL_STATUS_OK;
22032265
}
22042266

2267+
sl_status_t zwave_command_class_user_credential_credential_set_error_handle_report(
2268+
const zwave_controller_connection_info_t *connection_info,
2269+
const uint8_t *frame_data,
2270+
uint16_t frame_length)
2271+
{
2272+
if (frame_length < 13) {
2273+
sl_log_warning(LOG_TAG,
2274+
"CREDENTIAL_SET_ERROR_REPORT frame length is not valid");
2275+
return SL_STATUS_NOT_SUPPORTED;
2276+
}
2277+
2278+
// We don't need the rest of the frame, we just ensure that the attribute store is valid
2279+
uint8_t error_code = frame_data[2];
2280+
user_credential_user_unique_id_t user_id = get_uint16_value(frame_data, 3);
2281+
user_credential_type_t credential_type = frame_data[5];
2282+
user_credential_slot_t credential_slot = get_uint16_value(frame_data, 6);
2283+
2284+
2285+
attribute_store_node_t endpoint_node
2286+
= zwave_command_class_get_endpoint_node(connection_info);
2287+
attribute_store_node_t credential_type_node;
2288+
attribute_store_node_t credential_slot_node;
2289+
2290+
auto remove_credential_slot_if_possible = [&](attribute_store_node_t credential_slot_node) {
2291+
if (attribute_store_node_exists(credential_slot_node)) {
2292+
sl_log_debug(LOG_TAG,
2293+
"Removing credential slot : user %d, "
2294+
"credential type %d, credential slot %d",
2295+
user_id,
2296+
credential_type,
2297+
credential_slot);
2298+
attribute_store_delete_node(credential_slot_node);
2299+
} else {
2300+
sl_log_debug(LOG_TAG,
2301+
"No credential slot found for user %d, credential type "
2302+
"%d, credential slot %d",
2303+
user_id,
2304+
credential_type,
2305+
credential_slot);
2306+
}
2307+
};
2308+
switch(error_code) {
2309+
// Credential Add Rejected Location Occupied : 0x00
2310+
// If attempting to add a credential where a credential of that Credential Type at that Credential Slot already exists, and the new credential data differs
2311+
case CREDENTIAL_SET_ERROR_REPORT_CREDENTIALADDREJECTEDLOCATIONOCCUPIED:
2312+
sl_log_error(LOG_TAG,
2313+
"Credential data rejected as it already exists : user %d, "
2314+
"credential type %d, credential slot %d",
2315+
user_id,
2316+
credential_type,
2317+
credential_slot);
2318+
// Try to find the node in the store
2319+
get_credential_type_node(endpoint_node, user_id, credential_type, DESIRED_ATTRIBUTE, credential_type_node);
2320+
if (!attribute_store_node_exists(credential_type_node)) {
2321+
get_credential_type_node(endpoint_node, user_id, credential_type, REPORTED_ATTRIBUTE, credential_type_node);
2322+
}
2323+
2324+
get_credential_slot_node(credential_type_node, credential_slot, DESIRED_ATTRIBUTE, credential_slot_node);
2325+
2326+
remove_credential_slot_if_possible(credential_slot_node);
2327+
break;
2328+
// Credential Modify Rejected Location Empty : 0x01
2329+
case CREDENTIAL_SET_ERROR_REPORT_CREDENTIALMODIFYREJECTEDLOCATIONEMPTY:
2330+
sl_log_error(LOG_TAG,
2331+
"Credential data cannot be modified as it does not exists : user %d, "
2332+
"credential type %d, credential slot %d",
2333+
user_id,
2334+
credential_type,
2335+
credential_slot);
2336+
2337+
// Try to find the node in the store
2338+
get_credential_type_node(endpoint_node, user_id, credential_type, DESIRED_ATTRIBUTE, credential_type_node);
2339+
if (!attribute_store_node_exists(credential_type_node)) {
2340+
get_credential_type_node(endpoint_node, user_id, credential_type, REPORTED_ATTRIBUTE, credential_type_node);
2341+
}
2342+
2343+
if (!attribute_store_node_exists(credential_type_node)) {
2344+
sl_log_debug(LOG_TAG,
2345+
"No credential type found for user %d, credential type %d",
2346+
user_id,
2347+
credential_type);
2348+
return SL_STATUS_OK;
2349+
}
2350+
2351+
get_credential_slot_node(credential_type_node, credential_slot, DESIRED_ATTRIBUTE, credential_slot_node);
2352+
if (!attribute_store_node_exists(credential_slot_node)) {
2353+
get_credential_slot_node(credential_type_node, credential_slot, REPORTED_ATTRIBUTE, credential_slot_node);
2354+
}
2355+
2356+
remove_credential_slot_if_possible(credential_slot_node);
2357+
break;
2358+
// Duplicate Credential : 0x02
2359+
case CREDENTIAL_SET_ERROR_REPORT_DUPLICATECREDENTIAL:
2360+
// Do nothing, the credential GET will clean up for us
2361+
sl_log_warning(LOG_TAG,
2362+
"Duplicate Credential for user %d, credential type %d, "
2363+
"credential slot %d",
2364+
user_id,
2365+
credential_type,
2366+
credential_slot);
2367+
break;
2368+
// Manufacturer Security Rules : 0x03
2369+
case CREDENTIAL_SET_ERROR_REPORT_MANUFACTURERSECURITYRULES:
2370+
// Do nothing, the credential GET will clean up for us
2371+
sl_log_warning(
2372+
LOG_TAG,
2373+
"Credential data rejected as it doesn't respect manufacturer "
2374+
"security rules : user %d, credential type %d, "
2375+
"credential slot %d",
2376+
user_id,
2377+
credential_type,
2378+
credential_slot);
2379+
break;
2380+
}
2381+
2382+
return SL_STATUS_OK;
2383+
}
22052384
/////////////////////////////////////////////////////////////////////////////
22062385
// User Set/Get/Report/Set Error Report
22072386
/////////////////////////////////////////////////////////////////////////////
@@ -3212,6 +3391,11 @@ sl_status_t zwave_command_class_user_credential_control_handler(
32123391
connection_info,
32133392
frame_data,
32143393
frame_length);
3394+
case CREDENTIAL_SET_ERROR_REPORT:
3395+
return zwave_command_class_user_credential_credential_set_error_handle_report(
3396+
connection_info,
3397+
frame_data,
3398+
frame_length);
32153399
case USER_CAPABILITIES_REPORT:
32163400
return zwave_command_class_user_credential_user_capabilities_handle_report(
32173401
connection_info,

0 commit comments

Comments
 (0)