Added some missing services to APDU. Fix maxes. Refactor Simple Ack.

This commit is contained in:
Steve Karg
2022-11-06 10:34:44 -06:00
parent 64d1461549
commit a3fd5b9fc3
3 changed files with 135 additions and 161 deletions
+2 -1
View File
@@ -1478,7 +1478,7 @@ typedef enum BACnet_Confirmed_Service_Choice {
/* Services added after 2016 */ /* Services added after 2016 */
/* confirmed-audit-notification [32] see Alarm and Event Services */ /* confirmed-audit-notification [32] see Alarm and Event Services */
/* audit-log-query [33] see Object Access Services */ /* audit-log-query [33] see Object Access Services */
MAX_BACNET_CONFIRMED_SERVICE = 30 MAX_BACNET_CONFIRMED_SERVICE = 34
} BACNET_CONFIRMED_SERVICE; } BACNET_CONFIRMED_SERVICE;
/* BACnetUnconfirmedServiceChoice ::= ENUMERATED */ /* BACnetUnconfirmedServiceChoice ::= ENUMERATED */
@@ -1515,6 +1515,7 @@ typedef enum BACnet_Services_Supported {
/* Alarm and Event Services */ /* Alarm and Event Services */
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0, SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1, SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION_MULTIPLE = 42,
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION = 2, SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION = 2,
SERVICE_SUPPORTED_GET_ALARM_SUMMARY = 3, SERVICE_SUPPORTED_GET_ALARM_SUMMARY = 3,
SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY = 4, SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY = 4,
+129 -160
View File
@@ -76,7 +76,11 @@ static BACNET_SERVICES_SUPPORTED
SERVICE_SUPPORTED_AUTHENTICATE, SERVICE_SUPPORTED_REQUEST_KEY, SERVICE_SUPPORTED_AUTHENTICATE, SERVICE_SUPPORTED_REQUEST_KEY,
SERVICE_SUPPORTED_READ_RANGE, SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION, SERVICE_SUPPORTED_READ_RANGE, SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY, SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY,
SERVICE_SUPPORTED_GET_EVENT_INFORMATION SERVICE_SUPPORTED_GET_EVENT_INFORMATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY_MULTIPLE,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION_MULTIPLE,
SERVICE_SUPPORTED_CONFIRMED_AUDIT_NOTIFICATION,
SERVICE_SUPPORTED_AUDIT_LOG_QUERY
}; };
/* a simple table for crossing the services supported */ /* a simple table for crossing the services supported */
@@ -88,7 +92,13 @@ static BACNET_SERVICES_SUPPORTED
SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER, SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE, SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE,
SERVICE_SUPPORTED_TIME_SYNCHRONIZATION, SERVICE_SUPPORTED_WHO_HAS, SERVICE_SUPPORTED_TIME_SYNCHRONIZATION, SERVICE_SUPPORTED_WHO_HAS,
SERVICE_SUPPORTED_WHO_IS, SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION SERVICE_SUPPORTED_WHO_IS,
SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION,
SERVICE_SUPPORTED_WRITE_GROUP,
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION_MULTIPLE,
SERVICE_SUPPORTED_UNCONFIRMED_AUDIT_NOTIFICATION,
SERVICE_SUPPORTED_WHO_AM_I,
SERVICE_SUPPORTED_YOU_ARE
}; };
/* Confirmed Function Handlers */ /* Confirmed Function Handlers */
@@ -241,16 +251,24 @@ static union {
confirmed_ack_function complex; confirmed_ack_function complex;
} Confirmed_ACK_Function[MAX_BACNET_CONFIRMED_SERVICE]; } Confirmed_ACK_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_confirmed_simple_ack_handler( /**
BACNET_CONFIRMED_SERVICE service_choice, * @brief Determine if the BACnet service is a Simple Ack Service
confirmed_simple_ack_function pFunction) * @param service_choice [in] BACnet confirmed service choice
*/
bool apdu_confirmed_simple_ack_service(
BACNET_CONFIRMED_SERVICE service_choice)
{ {
bool status = false;
switch (service_choice) { switch (service_choice) {
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM: case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
case SERVICE_CONFIRMED_AUDIT_NOTIFICATION:
case SERVICE_CONFIRMED_COV_NOTIFICATION: case SERVICE_CONFIRMED_COV_NOTIFICATION:
case SERVICE_CONFIRMED_COV_NOTIFICATION_MULTIPLE:
case SERVICE_CONFIRMED_EVENT_NOTIFICATION: case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
case SERVICE_CONFIRMED_SUBSCRIBE_COV: case SERVICE_CONFIRMED_SUBSCRIBE_COV:
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY: case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY:
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY_MULTIPLE:
case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION: case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION:
/* Object Access Services */ /* Object Access Services */
case SERVICE_CONFIRMED_ADD_LIST_ELEMENT: case SERVICE_CONFIRMED_ADD_LIST_ELEMENT:
@@ -266,40 +284,29 @@ void apdu_set_confirmed_simple_ack_handler(
case SERVICE_CONFIRMED_VT_CLOSE: case SERVICE_CONFIRMED_VT_CLOSE:
/* Security Services */ /* Security Services */
case SERVICE_CONFIRMED_REQUEST_KEY: case SERVICE_CONFIRMED_REQUEST_KEY:
Confirmed_ACK_Function[service_choice].simple = pFunction; status = true;
break; break;
default: default:
break; break;
} }
return status;
}
void apdu_set_confirmed_simple_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_simple_ack_function pFunction)
{
if (apdu_confirmed_simple_ack_service(service_choice)) {
Confirmed_ACK_Function[service_choice].simple = pFunction;
}
} }
void apdu_set_confirmed_ack_handler( void apdu_set_confirmed_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice, confirmed_ack_function pFunction) BACNET_CONFIRMED_SERVICE service_choice, confirmed_ack_function pFunction)
{ {
switch (service_choice) { if (!apdu_confirmed_simple_ack_service(service_choice)) {
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY: Confirmed_ACK_Function[service_choice].complex = pFunction;
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
/* File Access Services */
case SERVICE_CONFIRMED_ATOMIC_READ_FILE:
case SERVICE_CONFIRMED_ATOMIC_WRITE_FILE:
/* Object Access Services */
case SERVICE_CONFIRMED_CREATE_OBJECT:
case SERVICE_CONFIRMED_READ_PROPERTY:
case SERVICE_CONFIRMED_READ_PROP_CONDITIONAL:
case SERVICE_CONFIRMED_READ_PROP_MULTIPLE:
case SERVICE_CONFIRMED_READ_RANGE:
/* Remote Device Management Services */
case SERVICE_CONFIRMED_PRIVATE_TRANSFER:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_OPEN:
case SERVICE_CONFIRMED_VT_DATA:
/* Security Services */
case SERVICE_CONFIRMED_AUTHENTICATE:
Confirmed_ACK_Function[service_choice].complex = pFunction;
break;
default:
break;
} }
} }
@@ -578,109 +585,68 @@ void apdu_handler(BACNET_ADDRESS *src,
} }
break; break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
if (apdu_len >= 2) { if (apdu_len < 3) {
service_choice = apdu[1]; break;
service_request = &apdu[2]; }
service_request_len = apdu_len - 2; service_choice = apdu[1];
if (apdu_unconfirmed_dcc_disabled(service_choice)) { service_request = &apdu[2];
/* When network communications are disabled, service_request_len = apdu_len - 2;
only DeviceCommunicationControl and if (apdu_unconfirmed_dcc_disabled(service_choice)) {
ReinitializeDevice APDUs shall be processed and no /* When network communications are disabled,
messages shall be initiated. If communications have only DeviceCommunicationControl and
been initiation disabled, then WhoIs may be ReinitializeDevice APDUs shall be processed and no
processed. */ messages shall be initiated. If communications have
break; been initiation disabled, then WhoIs may be
} processed. */
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) { break;
if (Unconfirmed_Function[service_choice]) { }
Unconfirmed_Function[service_choice]( if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
service_request, service_request_len, src); if (Unconfirmed_Function[service_choice]) {
} Unconfirmed_Function[service_choice](
service_request, service_request_len, src);
} }
} }
break; break;
case PDU_TYPE_SIMPLE_ACK: case PDU_TYPE_SIMPLE_ACK:
if (apdu_len >= 3) { if (apdu_len < 3) {
invoke_id = apdu[1]; break;
service_choice = apdu[2]; }
switch (service_choice) { invoke_id = apdu[1];
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM: service_choice = apdu[2];
case SERVICE_CONFIRMED_COV_NOTIFICATION: if (apdu_confirmed_simple_ack_service(service_choice)) {
case SERVICE_CONFIRMED_EVENT_NOTIFICATION: if (Confirmed_ACK_Function[service_choice].simple !=
case SERVICE_CONFIRMED_SUBSCRIBE_COV: NULL) {
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY: Confirmed_ACK_Function[service_choice].simple(
case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION: src, invoke_id);
/* Object Access Services */
case SERVICE_CONFIRMED_ADD_LIST_ELEMENT:
case SERVICE_CONFIRMED_REMOVE_LIST_ELEMENT:
case SERVICE_CONFIRMED_DELETE_OBJECT:
case SERVICE_CONFIRMED_WRITE_PROPERTY:
case SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE:
/* Remote Device Management Services */
case SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL:
case SERVICE_CONFIRMED_REINITIALIZE_DEVICE:
case SERVICE_CONFIRMED_TEXT_MESSAGE:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_CLOSE:
/* Security Services */
case SERVICE_CONFIRMED_REQUEST_KEY:
if (Confirmed_ACK_Function[service_choice].simple !=
NULL) {
Confirmed_ACK_Function[service_choice].simple(
src, invoke_id);
}
tsm_free_invoke_id(invoke_id);
break;
default:
break;
} }
tsm_free_invoke_id(invoke_id);
} }
break; break;
case PDU_TYPE_COMPLEX_ACK: case PDU_TYPE_COMPLEX_ACK:
if (apdu_len >= 3) { if (apdu_len < 3) {
service_ack_data.segmented_message = break;
(apdu[0] & BIT(3)) ? true : false; }
service_ack_data.more_follows = service_ack_data.segmented_message =
(apdu[0] & BIT(2)) ? true : false; (apdu[0] & BIT(3)) ? true : false;
invoke_id = service_ack_data.invoke_id = apdu[1]; service_ack_data.more_follows =
len = 2; (apdu[0] & BIT(2)) ? true : false;
if (service_ack_data.segmented_message) { invoke_id = service_ack_data.invoke_id = apdu[1];
service_ack_data.sequence_number = apdu[len++]; len = 2;
service_ack_data.proposed_window_number = apdu[len++]; if (service_ack_data.segmented_message) {
} service_ack_data.sequence_number = apdu[len++];
service_choice = apdu[len++]; service_ack_data.proposed_window_number = apdu[len++];
service_request = &apdu[len]; }
service_request_len = apdu_len - (uint16_t)len; service_choice = apdu[len++];
switch (service_choice) { service_request = &apdu[len];
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY: service_request_len = apdu_len - (uint16_t)len;
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY: if (!apdu_confirmed_simple_ack_service(service_choice)) {
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION: if (Confirmed_ACK_Function[service_choice]
/* File Access Services */ .complex != NULL) {
case SERVICE_CONFIRMED_ATOMIC_READ_FILE: Confirmed_ACK_Function[service_choice].complex(
case SERVICE_CONFIRMED_ATOMIC_WRITE_FILE: service_request, service_request_len, src,
/* Object Access Services */ &service_ack_data);
case SERVICE_CONFIRMED_CREATE_OBJECT:
case SERVICE_CONFIRMED_READ_PROPERTY:
case SERVICE_CONFIRMED_READ_PROP_CONDITIONAL:
case SERVICE_CONFIRMED_READ_PROP_MULTIPLE:
case SERVICE_CONFIRMED_READ_RANGE:
case SERVICE_CONFIRMED_PRIVATE_TRANSFER:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_OPEN:
case SERVICE_CONFIRMED_VT_DATA:
/* Security Services */
case SERVICE_CONFIRMED_AUTHENTICATE:
if (Confirmed_ACK_Function[service_choice]
.complex != NULL) {
Confirmed_ACK_Function[service_choice].complex(
service_request, service_request_len, src,
&service_ack_data);
}
tsm_free_invoke_id(invoke_id);
break;
default:
break;
} }
tsm_free_invoke_id(invoke_id);
} }
break; break;
case PDU_TYPE_SEGMENT_ACK: case PDU_TYPE_SEGMENT_ACK:
@@ -688,49 +654,52 @@ void apdu_handler(BACNET_ADDRESS *src,
we could check src to see if that matched the tsm */ we could check src to see if that matched the tsm */
tsm_free_invoke_id(invoke_id); tsm_free_invoke_id(invoke_id);
break; break;
case PDU_TYPE_ERROR: case PDU_TYPE_ERROR:
if (apdu_len >= 3) { if (apdu_len < 3) {
invoke_id = apdu[1]; break;
service_choice = apdu[2];
if (apdu_complex_error(service_choice)) {
if (Error_Function[service_choice].complex) {
Error_Function[service_choice].complex(src,
invoke_id, service_choice, &apdu[3],
apdu_len - 3);
}
} else if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
len = bacerror_decode_error_class_and_code(
&apdu[3], apdu_len - 3, &error_class, &error_code);
if ((len != 0) &&
(Error_Function[service_choice].error)) {
Error_Function[service_choice].error(src, invoke_id,
(BACNET_ERROR_CLASS)error_class,
(BACNET_ERROR_CODE)error_code);
}
}
tsm_free_invoke_id(invoke_id);
} }
invoke_id = apdu[1];
service_choice = apdu[2];
if (apdu_complex_error(service_choice)) {
if (Error_Function[service_choice].complex) {
Error_Function[service_choice].complex(src,
invoke_id, service_choice, &apdu[3],
apdu_len - 3);
}
} else if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
len = bacerror_decode_error_class_and_code(
&apdu[3], apdu_len - 3, &error_class, &error_code);
if ((len != 0) &&
(Error_Function[service_choice].error)) {
Error_Function[service_choice].error(src, invoke_id,
(BACNET_ERROR_CLASS)error_class,
(BACNET_ERROR_CODE)error_code);
}
}
tsm_free_invoke_id(invoke_id);
break; break;
case PDU_TYPE_REJECT: case PDU_TYPE_REJECT:
if (apdu_len >= 3) { if (apdu_len < 3) {
invoke_id = apdu[1]; break;
reason = apdu[2];
if (Reject_Function) {
Reject_Function(src, invoke_id, reason);
}
tsm_free_invoke_id(invoke_id);
} }
invoke_id = apdu[1];
reason = apdu[2];
if (Reject_Function) {
Reject_Function(src, invoke_id, reason);
}
tsm_free_invoke_id(invoke_id);
break; break;
case PDU_TYPE_ABORT: case PDU_TYPE_ABORT:
if (apdu_len >= 3) { if (apdu_len < 3) {
server = apdu[0] & 0x01; break;
invoke_id = apdu[1];
reason = apdu[2];
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
tsm_free_invoke_id(invoke_id);
} }
server = apdu[0] & 0x01;
invoke_id = apdu[1];
reason = apdu[2];
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
tsm_free_invoke_id(invoke_id);
break; break;
default: default:
break; break;
+4
View File
@@ -125,6 +125,10 @@ extern "C" {
BACNET_CONFIRMED_SERVICE service_choice, BACNET_CONFIRMED_SERVICE service_choice,
confirmed_ack_function pFunction); confirmed_ack_function pFunction);
BACNET_STACK_EXPORT
bool apdu_confirmed_simple_ack_service(
BACNET_CONFIRMED_SERVICE service_choice);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void apdu_set_confirmed_simple_ack_handler( void apdu_set_confirmed_simple_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice, BACNET_CONFIRMED_SERVICE service_choice,