diff options
| author | Scott Larson <[email protected]> | 2021-01-07 18:16:40 -0800 |
|---|---|---|
| committer | Scott Larson <[email protected]> | 2021-01-07 18:16:40 -0800 |
| commit | 699d64dc5e4ef6cedd42401bc10cf9f3be0b476b (patch) | |
| tree | d0e31ccb944f81f30b83184b49f19dd337cc5adc | |
| parent | f66451ca193a96b5734e9a99d6d0ed9de44c9ac5 (diff) | |
update to v6.1.3
43 files changed, 6964 insertions, 150 deletions
@@ -96,4 +96,4 @@ The following are references to additional Azure RTOS and Azure IoT in general: | Azure RTOS Sales Questions: | https://azure-rtos.ms-iot-contact.com/ | | Microsoft Q/A for Azure IoT: | https://docs.microsoft.com/en-us/answers/products/azure?product=iot | | Internet of Things Show: | https://aka.ms/iotshow | -| IoT Tech Community: | https://aka.ms/iottechcommunity | +| IoT Tech Community: | https://aka.ms/iottechcommunity |
\ No newline at end of file diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt index cfe60389..39c80e95 100644 --- a/addons/CMakeLists.txt +++ b/addons/CMakeLists.txt @@ -14,6 +14,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/ftp/nxd_ftp_server.c ${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_client.c ${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_server.c + ${CMAKE_CURRENT_LIST_DIR}/lwm2m/nx_lwm2m_client.c ${CMAKE_CURRENT_LIST_DIR}/mdns/nxd_mdns.c ${CMAKE_CURRENT_LIST_DIR}/mqtt/nxd_mqtt_client.c ${CMAKE_CURRENT_LIST_DIR}/nat/nx_nat.c @@ -21,6 +22,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/ppp/nx_ppp.c ${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_client.c ${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_server.c + ${CMAKE_CURRENT_LIST_DIR}/ptp/nxd_ptp_client.c ${CMAKE_CURRENT_LIST_DIR}/smtp/nxd_smtp_client.c ${CMAKE_CURRENT_LIST_DIR}/snmp/nx_des.c ${CMAKE_CURRENT_LIST_DIR}/snmp/nx_sha1.c @@ -84,12 +86,14 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dns ${CMAKE_CURRENT_LIST_DIR}/ftp ${CMAKE_CURRENT_LIST_DIR}/http + ${CMAKE_CURRENT_LIST_DIR}/lwm2m ${CMAKE_CURRENT_LIST_DIR}/mdns ${CMAKE_CURRENT_LIST_DIR}/mqtt ${CMAKE_CURRENT_LIST_DIR}/nat ${CMAKE_CURRENT_LIST_DIR}/pop3 ${CMAKE_CURRENT_LIST_DIR}/ppp ${CMAKE_CURRENT_LIST_DIR}/pppoe + ${CMAKE_CURRENT_LIST_DIR}/ptp ${CMAKE_CURRENT_LIST_DIR}/smtp ${CMAKE_CURRENT_LIST_DIR}/snmp ${CMAKE_CURRENT_LIST_DIR}/sntp diff --git a/addons/azure_iot/azure-sdk-for-c b/addons/azure_iot/azure-sdk-for-c -Subproject 5e9d7b96dbd98ce7125e4beed385959a32b4c6c +Subproject c305408ce67e98e1417bb7518ae2743b8c397ec diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c index b148e535..08d48a7a 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c @@ -123,7 +123,7 @@ asc_result_t core_collect(core_t *core_ptr) current_collector=current_collector->next ) { uint32_t last_collected = collector_get_last_collected_timestamp(current_collector); - double interval = priority_collectors_get_interval(prioritized_collectors); + uint32_t interval = priority_collectors_get_interval(prioritized_collectors); if (current_snapshot - last_collected >= interval) { time_passed = true; diff --git a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md index ea912887..2fcdba02 100644 --- a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md +++ b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md @@ -167,7 +167,7 @@ UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_pt ``` **Description** -<p>This routine sets the Device Twin model id. Note: THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE.</p> +<p>This routine sets the Device Twin model id.</p> **Parameters** diff --git a/addons/azure_iot/nx_azure_iot_hub_client.c b/addons/azure_iot/nx_azure_iot_hub_client.c index 3cdff666..0b15d58e 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.c +++ b/addons/azure_iot/nx_azure_iot_hub_client.c @@ -302,7 +302,7 @@ az_result core_result; /* Build client id. */ buffer_length = buffer_size; core_result = az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core), - (CHAR *)buffer_ptr, buffer_length, &buffer_length); + (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length); if (az_result_failed(core_result)) { @@ -322,7 +322,7 @@ az_result core_result; /* Build user name. */ buffer_length = buffer_size; core_result = az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core, - (CHAR *)buffer_ptr, buffer_length, &buffer_length); + (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length); if (az_result_failed(core_result)) { @@ -786,7 +786,7 @@ az_result core_result; topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); core_result = az_iot_hub_client_telemetry_get_publish_topic(&hub_client_ptr -> iot_hub_client_core, NULL, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - topic_length, &topic_length); + topic_length, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub client telemetry message create fail with error status: %d"), core_result); @@ -1569,7 +1569,7 @@ USHORT length; core_result = az_iot_hub_client_twin_patch_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - buffer_size, &topic_length); + buffer_size, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub client reported state send fail: NX_AZURE_IOT_HUB_CLIENT_TOPIC_SIZE is too small.")); @@ -1741,7 +1741,7 @@ az_result core_result; core_result = az_iot_hub_client_twin_document_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - buffer_size, &topic_length); + buffer_size, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub client device twin get topic fail.")); @@ -2429,7 +2429,7 @@ az_result core_result; buffer_span = az_span_create(output_ptr, (INT)output_len); core_result= az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core), expiry_time_secs, buffer_span, AZ_SPAN_EMPTY, - (CHAR *)sas_buffer, sas_buffer_len, &sas_buffer_len); + (CHAR *)sas_buffer, sas_buffer_len, (size_t *)&sas_buffer_len); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result); @@ -2622,7 +2622,7 @@ az_result core_result; core_result = az_iot_hub_client_methods_response_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), request_id_span, (USHORT)status_code, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - topic_length, &topic_length); + topic_length, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("Failed to create the method response topic")); diff --git a/addons/azure_iot/nx_azure_iot_hub_client.h b/addons/azure_iot/nx_azure_iot_hub_client.h index a510bb81..69a5348a 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.h +++ b/addons/azure_iot/nx_azure_iot_hub_client.h @@ -227,8 +227,6 @@ UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_clie /** * @brief Set Device Twin model id in the IoT Hub client. * - * @warning THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE. - * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. * @param[in] model_id_ptr A pointer to a model id. * @param[in] model_id_length Length of `model id`. diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.c b/addons/azure_iot/nx_azure_iot_provisioning_client.c index 78a4d014..3ab6fb2f 100644 --- a/addons/azure_iot/nx_azure_iot_provisioning_client.c +++ b/addons/azure_iot/nx_azure_iot_provisioning_client.c @@ -638,13 +638,15 @@ az_result core_result; if (register_response == NULL) { core_result = az_iot_provisioning_client_register_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), - (CHAR *)buffer_ptr, buffer_size, &mqtt_topic_length); + (CHAR *)buffer_ptr, buffer_size, + (size_t *)&mqtt_topic_length); } else { core_result = az_iot_provisioning_client_query_status_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), register_response -> operation_id, (CHAR *)buffer_ptr, - buffer_size, &mqtt_topic_length); + buffer_size, + (size_t *)&mqtt_topic_length); } if (az_result_failed(core_result)) @@ -772,7 +774,7 @@ az_span policy_name = AZ_SPAN_LITERAL_FROM_STR(NX_AZURE_IOT_PROVISIONING_CLIENT_ buffer_span, expiry_time_secs, policy_name, (CHAR *)resource_ptr -> resource_mqtt_sas_token, prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size, - &(resource_ptr -> resource_mqtt_sas_token_length)); + (size_t *)&(resource_ptr -> resource_mqtt_sas_token_length)); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTProvisioning failed to generate token with error : %d"), core_result); @@ -892,7 +894,8 @@ az_span registration_id_span = az_span_create((UCHAR *)registration_id, (INT)reg /* Build user name. */ if (az_result_failed(az_iot_provisioning_client_get_user_name(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), - (CHAR *)buffer_ptr, buffer_size, &mqtt_user_name_length))) + (CHAR *)buffer_ptr, buffer_size, + (size_t *)&mqtt_user_name_length))) { LogError(LogLiteralArgs("IoTProvisioning client connect fail: NX_AZURE_IOT_Provisioning_CLIENT_USERNAME_SIZE is too small.")); nx_azure_iot_buffer_free(buffer_context); diff --git a/addons/dhcp/nxd_dhcp_server.c b/addons/dhcp/nxd_dhcp_server.c index 4c02ad5f..90143562 100644 --- a/addons/dhcp/nxd_dhcp_server.c +++ b/addons/dhcp/nxd_dhcp_server.c @@ -2558,7 +2558,7 @@ CHAR *work_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_parse_next_option PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2581,7 +2581,7 @@ CHAR *work_ptr; /* */ /* CALLS */ /* */ -/* atoi Convert ascii number to integer*/ +/* _nx_utility_string_to_uint Convert ascii number to integer*/ /* */ /* CALLED BY */ /* */ @@ -2594,6 +2594,9 @@ CHAR *work_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), fixed */ +/* obsolescent functions, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dhcp_parse_next_option(CHAR **option_list, UINT *option, UINT length) @@ -2656,10 +2659,8 @@ CHAR *buffer; *option_list += j; - /* Convert the number string to an actual integer. */ - *option = (UINT) atoi(num_string); - - return(NX_SUCCESS); + /* Convert the number string to an actual unsigned integer. */ + return(_nx_utility_string_to_uint(num_string, buffer_index, option)); } diff --git a/addons/dns/nxd_dns.c b/addons/dns/nxd_dns.c index 9726beff..64bd6180 100644 --- a/addons/dns/nxd_dns.c +++ b/addons/dns/nxd_dns.c @@ -67,7 +67,7 @@ static UINT _nx_dns_process_a_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr static UINT _nx_dns_process_aaaa_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count, UINT rr_location); #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES -static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start); +static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length); static UINT _nx_dns_process_cname_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); static UINT _nx_dns_process_txt_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count); @@ -6175,7 +6175,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_ns_type PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6222,6 +6222,10 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/ +/* API to get the real size of */ +/* resource name, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -6291,7 +6295,7 @@ ULONG rr_ttl; } /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_NS_ENTRY))) @@ -6378,7 +6382,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_mx_type PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6426,6 +6430,10 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/ +/* API to get the real size of */ +/* resource name, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_mx_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -6504,7 +6512,7 @@ UINT size; data_ptr += 2; /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY))) @@ -6609,7 +6617,7 @@ UINT size; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_srv_type PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6657,6 +6665,10 @@ UINT size; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Updated input parameter of the*/ +/* API to get the real size of */ +/* resource name, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_srv_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, @@ -6748,7 +6760,7 @@ UINT size; data_ptr += 2; /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY))) @@ -8108,7 +8120,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_dns_name_string_unencode PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8146,6 +8158,10 @@ UINT count = 1; /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* compression pointer check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dns_name_string_unencode(NX_PACKET *packet_ptr, UCHAR *data, UCHAR *buffer, UINT buffer_size) @@ -8156,7 +8172,8 @@ UCHAR *message_start; UINT label_size; UINT offset; UINT length; - +UINT pointer_count = 0; + /* Initialize the value. */ character = data; message_start = packet_ptr -> nx_packet_prepend_ptr; @@ -8218,6 +8235,14 @@ UINT length; } else { + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS) + { + + /* This is malformed packet. */ + return(0); + } /* update valid pointer */ character = message_start + offset; } @@ -8354,7 +8379,7 @@ UINT size = 0; /* FUNCTION RELEASE */ /* */ /* _nx_dns_resource_name_real_size_calculate PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8367,6 +8392,7 @@ UINT size = 0; /* */ /* data Pointer to buffer to decode */ /* start Location of start of data */ +/* data_length Data buffer length */ /* */ /* OUTPUT */ /* */ @@ -8388,14 +8414,20 @@ UINT size = 0; /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* compression pointer check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* pointer check, prevented */ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ -static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start) +static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length) { UCHAR *character = data + start; UINT length = 0; - +UINT offset; +UINT pointer_count = 0; /* As long as there is space in the buffer and we haven't found a zero terminating label */ @@ -8422,8 +8454,18 @@ UINT length = 0; else if ((labelSize & NX_DNS_COMPRESS_MASK) == NX_DNS_COMPRESS_VALUE) { + /* Get the offset. */ + offset = ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character; + + /* Check the offset. */ + if (offset >= data_length) + { + + return(0); + } + /* This is a pointer, just adjust the source. */ - if (character == data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character) + if (character == data + offset) { /* If compression pointer equals the same offset currently being parsed, it could lead to an infinite loop. */ @@ -8431,8 +8473,19 @@ UINT length = 0; } else { + + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + + if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS) + { + + /* This is malformed packet. */ + return(0); + } + /* update valid pointer */ - character = data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character; + character = data + offset; } } else @@ -8442,9 +8495,12 @@ UINT length = 0; return(0); } } - + /* Reduce the last '.' string, update the length. */ - length --; + if (length) + { + length --; + } /* Return name size. */ return(length); diff --git a/addons/dns/nxd_dns.h b/addons/dns/nxd_dns.h index c529db8d..39ea0045 100644 --- a/addons/dns/nxd_dns.h +++ b/addons/dns/nxd_dns.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dns.h PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ /* */ /**************************************************************************/ @@ -295,6 +299,10 @@ extern "C" { #define NX_DNS_PACKET_ALLOCATE_TIMEOUT NX_IP_PERIODIC_RATE #endif +/* Define the maximum number of pointers allowed in name compression. */ +#ifndef NX_DNS_MAX_COMPRESSION_POINTERS +#define NX_DNS_MAX_COMPRESSION_POINTERS 16 +#endif /* Define the basic DNS data structure. */ diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c index 6bedfa4c..f7071a70 100644 --- a/addons/ftp/nxd_ftp_server.c +++ b/addons/ftp/nxd_ftp_server.c @@ -1523,7 +1523,7 @@ ULONG events; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_command_process PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1595,6 +1595,9 @@ ULONG events; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ VOID _nx_ftp_server_command_process(NX_FTP_SERVER *ftp_server_ptr) @@ -1942,6 +1945,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "File Open Fail"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2223,6 +2238,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "File Open Failed"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2401,6 +2428,18 @@ ULONG block_size; case NX_FTP_RNFR: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Rename File not found"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2467,6 +2506,18 @@ ULONG block_size; case NX_FTP_RNTO: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Rename failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2537,6 +2588,18 @@ ULONG block_size; case NX_FTP_DELE: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Delete Failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2593,6 +2656,18 @@ ULONG block_size; case NX_FTP_RMD: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Delete Directory Fail"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2655,6 +2730,18 @@ ULONG block_size; case NX_FTP_MKD: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Directory Create failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2761,6 +2848,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "List bad Directory"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -3134,6 +3233,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Bad Directory"); + break; + } + /* Change to the default directory of this connection. */ status = fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -4113,6 +4224,9 @@ ULONG block_size; /* If CDUP command, create the "up one directory" pathname string. */ if (ftp_command == NX_FTP_CDUP) { + + /* Move the pointer to make sure there is enough memory to store the data. */ + buffer_ptr -= 3; buffer_ptr[0] = '.'; buffer_ptr[1] = '.'; buffer_ptr[2] = NX_NULL; @@ -4122,6 +4236,18 @@ ULONG block_size; else { + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Change Dir Fail"); + break; + } + /* Find the end of the message. */ j = 0; while (j < packet_ptr -> nx_packet_length - 1) @@ -4993,7 +5119,7 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_parse_command PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5027,6 +5153,9 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ftp_server_parse_command(NX_PACKET *packet_ptr) @@ -5036,6 +5165,14 @@ UINT i; char *buffer_ptr; + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message, just return INVALID. */ + return(NX_FTP_INVALID); + } + /* Setup pointer to command buffer area. */ buffer_ptr = (char *) packet_ptr -> nx_packet_prepend_ptr; @@ -5719,7 +5856,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_utility_parse_IPv6_address PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5763,6 +5900,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* colons count verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ftp_utility_parse_IPv6_address(CHAR *buffer_ptr, UINT buffer_length, NXD_ADDRESS *ipduo_address) @@ -5898,6 +6038,12 @@ ULONG temp; else if (buffer_ptr[j] == ':') { + /* Check if colons is valid. */ + if (colons >= 7) + { + return NX_FTP_INVALID_ADDRESS; + } + /* Increment the colon count. */ colons++; @@ -5963,6 +6109,12 @@ ULONG temp; m++; } + /* Check if colons is valid. */ + if (actual_colons_left >= remaining_colons) + { + return NX_FTP_INVALID_ADDRESS; + } + /* Compute the number of zeros to insert into the NXD_ADDRESS IPv6 ULONG array. */ number_consecutive_zeros_to_add = remaining_colons - actual_colons_left; diff --git a/addons/mdns/nxd_mdns.c b/addons/mdns/nxd_mdns.c index 4439cfe0..3f037904 100644 --- a/addons/mdns/nxd_mdns.c +++ b/addons/mdns/nxd_mdns.c @@ -85,7 +85,7 @@ static UINT _nx_mdns_rr_size_get(UCHAR *resource); static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length); static UINT _nx_mdns_name_size_calculate(UCHAR *name); static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name); -static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size); +static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size); static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name); static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size); static VOID _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value); @@ -9632,7 +9632,7 @@ UINT rr_name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_set PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -9671,6 +9671,9 @@ UINT rr_name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index) @@ -9713,8 +9716,9 @@ UINT temp_string_length; /* Process the name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), - temp_string_buffer, NX_MDNS_NAME_MAX)) + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, + temp_string_buffer, NX_MDNS_NAME_MAX)) { /* Check string length. */ @@ -9776,7 +9780,7 @@ UINT temp_string_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_process PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -9818,6 +9822,9 @@ UINT temp_string_length; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index) @@ -9847,8 +9854,9 @@ UINT rr_name_length; /* Process the name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), - temp_string_buffer, NX_MDNS_NAME_MAX)) + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, + temp_string_buffer, NX_MDNS_NAME_MAX)) { /* Check string length. */ @@ -10079,7 +10087,7 @@ UINT rr_name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_data_set PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -10121,6 +10129,9 @@ UINT rr_name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op) @@ -10285,7 +10296,8 @@ UINT temp_string_length; /* Process the target/domain name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, temp_string_buffer, NX_MDNS_NAME_MAX)) { @@ -13567,7 +13579,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_txt_string_decode PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13605,6 +13617,9 @@ UINT count = 1; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size) @@ -13628,7 +13643,7 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf { /* Simple count, check for space and copy the label. */ - while (labelSize > 0) + while ((labelSize > 0) && (data_length > 1)) { *buffer++ = *data++; @@ -13842,7 +13857,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_name_string_decode PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13857,6 +13872,7 @@ UINT count = 1; /* */ /* data Pointer to buffer to decode */ /* start Location of start of data */ +/* data_length Length of data buffer */ /* buffer Pointer to decoded data */ /* size Size of data buffer to decode */ /* */ @@ -13878,13 +13894,20 @@ UINT count = 1; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* prevented infinite loop in */ +/* name compression, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ -static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size) +static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size) { UCHAR *character = data + start; UINT length = 0; +UINT offset; +UINT pointer_count = 0; /* As long as there is space in the buffer and we haven't @@ -13915,7 +13938,28 @@ UINT length = 0; { /* This is a pointer, just adjust the source. */ - character = data + ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character; + offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character; + + /* Make sure offset is in the buffer. */ + if (offset >= data_length) + { + return(0); + } + + /* Pointer must not point back to itself. */ + if ((data + offset == character) || (data + offset == character - 1)) + { + return(0); + } + + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS) + { + return(0); + } + + character = data + offset; } else { @@ -13926,7 +13970,7 @@ UINT length = 0; } /* Done copying the data, set the last . to a trailing null */ - if (*(buffer - 1) == '.') + if ((length > 0) && (*(buffer - 1) == '.')) { buffer--; diff --git a/addons/mdns/nxd_mdns.h b/addons/mdns/nxd_mdns.h index 9f0faa6b..3287ab2c 100644 --- a/addons/mdns/nxd_mdns.h +++ b/addons/mdns/nxd_mdns.h @@ -25,7 +25,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_mdns.h PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,10 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), */ +/* prevented infinite loop in */ +/* name compression, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -378,6 +382,11 @@ extern "C" { #define NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT NX_IP_PERIODIC_RATE #endif /* NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT */ +/* Define the maximum number of pointers allowed in name compression. */ +#ifndef NX_MDNS_MAX_COMPRESSION_POINTERS +#define NX_MDNS_MAX_COMPRESSION_POINTERS 16 +#endif /* NX_MDNS_MAX_COMPRESSION_POINTERS */ + /* Define the default mDNS's announcing value. */ #define NX_MDNS_ANNOUNCING_PERIOD NX_IP_PERIODIC_RATE diff --git a/addons/pppoe/nx_pppoe_client.c b/addons/pppoe/nx_pppoe_client.c index 7959cd0f..38ebaa8a 100644 --- a/addons/pppoe/nx_pppoe_client.c +++ b/addons/pppoe/nx_pppoe_client.c @@ -609,7 +609,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_service_name_set_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -650,6 +650,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_pppoe_client_service_name_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *service_name, UINT service_name_length) @@ -671,6 +674,9 @@ UINT temp_service_name_length = 0; /* Setup service name pointer. */ pppoe_client_ptr -> nx_pppoe_service_name = service_name; + /* Setup service name length. */ + pppoe_client_ptr -> nx_pppoe_service_name_length = service_name_length; + /* Release the IP internal mutex. */ tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection)); @@ -869,7 +875,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_host_uniq_set_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -910,6 +916,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_pppoe_client_host_uniq_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *host_uniq, UINT host_uniq_length) @@ -927,8 +936,11 @@ UINT temp_host_uniq_length = 0; /* Obtain the IP internal mutex before processing the IP event. */ tx_mutex_get(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); - /* Setup service name pointer. */ + /* Setup host unique pointer. */ pppoe_client_ptr -> nx_pppoe_host_uniq = host_uniq; + + /* Setup host unique length. */ + pppoe_client_ptr -> nx_pppoe_host_uniq_length = host_uniq_length; /* Release the IP internal mutex. */ tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection)); @@ -2160,7 +2172,7 @@ UINT ethernet_type; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_discovery_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2203,6 +2215,9 @@ UINT ethernet_type; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ VOID _nx_pppoe_client_discovery_packet_process(NX_PPPOE_CLIENT *pppoe_client_ptr, NX_PACKET *packet_ptr, ULONG server_mac_msw, ULONG server_mac_lsw) @@ -2367,7 +2382,8 @@ UINT tag_host_uniq_valid = NX_FALSE; { /* Compare the service name with PPPoE Service name that Client is requesting. */ - if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length)) + if ((pppoe_client_ptr -> nx_pppoe_service_name_length == tag_length) && + (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length))) { /* Update the information. */ @@ -2407,7 +2423,8 @@ UINT tag_host_uniq_valid = NX_FALSE; tag_host_uniq_count ++; /* Check the Host-Uniq. */ - if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length)) + if ((pppoe_client_ptr -> nx_pppoe_host_uniq_length == tag_length) && + (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length))) { /* Update the information. */ @@ -2754,7 +2771,7 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_discovery_send PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2796,6 +2813,9 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_pppoe_client_discovery_send(NX_PPPOE_CLIENT *pppoe_client_ptr, UINT code) @@ -2806,7 +2826,6 @@ NX_PACKET *packet_ptr; UCHAR *work_ptr; UINT status; UINT index = 0; -UINT tag_length; /* Allocate a PPPoE packet. */ @@ -2846,21 +2865,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_service_name) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_service_name_length)) { /* Added the Service-Name tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); } else { @@ -2881,21 +2891,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_host_uniq) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length)) { /* Added the Host-Uniq tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); } else { @@ -2914,22 +2915,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_service_name) { - - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_service_name_length)) { /* Added the Service-Name tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); } else { @@ -2950,21 +2941,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_host_uniq) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length)) { /* Added the Host-Uniq tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); } else { diff --git a/addons/pppoe/nx_pppoe_client.h b/addons/pppoe/nx_pppoe_client.h index 8c03978e..64637e99 100644 --- a/addons/pppoe/nx_pppoe_client.h +++ b/addons/pppoe/nx_pppoe_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_pppoe_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -228,7 +231,9 @@ typedef struct NX_PPPOE_CLIENT_STRUCT UINT nx_pppoe_state; NX_PPPOE_SERVER_SESSION nx_pppoe_server_session; UCHAR *nx_pppoe_service_name; + UINT nx_pppoe_service_name_length; UCHAR *nx_pppoe_host_uniq; + UINT nx_pppoe_host_uniq_length; UCHAR nx_pppoe_ac_name[NX_PPPOE_CLIENT_MAX_AC_NAME_SIZE]; UINT nx_pppoe_ac_name_size; UCHAR nx_pppoe_ac_cookie[NX_PPPOE_CLIENT_MAX_AC_COOKIE_SIZE]; diff --git a/addons/ptp/nxd_ptp_client.c b/addons/ptp/nxd_ptp_client.c new file mode 100644 index 00000000..1be23884 --- /dev/null +++ b/addons/ptp/nxd_ptp_client.c @@ -0,0 +1,3736 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX PTP Client Component */ +/** */ +/** Precision Time Protocol (PTP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nxd_ptp_client.c PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX Precision Time Protocol (PTP) */ +/* Client component, including all data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + + +/* Force error checking to be disabled in this module */ + +#ifndef NX_DISABLE_ERROR_CHECKING +#define NX_DISABLE_ERROR_CHECKING +#endif + +#define NX_PTP_SOURCE_CODE + +#include "nxd_ptp_client.h" +#include "nx_udp.h" +#include "nx_ipv4.h" +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +#include "nx_ipv6.h" +#endif +#include "tx_timer.h" + +/* #define NX_PTP_DEBUG */ +/* #define NX_PTP_DEBUG_OFFSET */ +#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET) +#include <stdio.h> +#endif +#ifdef NX_PTP_DEBUG +#ifndef NX_PTP_DEBUG_PRINTF +#define NX_PTP_DEBUG_PRINTF(x) printf x +#endif +#else +#define NX_PTP_DEBUG_PRINTF(x) +#endif + +/* Bring in externs for caller checking code. */ + +NX_CALLER_CHECKING_EXTERNS + +/* number of nanoseconds per second */ +#define NX_PTP_NANOSECONDS_PER_SEC 1000000000L + +/* Define the PTP version */ +#define NX_PTP_VERSION 2 + +/* Define the UDP ports */ +#define NX_PTP_EVENT_UDP_PORT 319 +#define NX_PTP_GENERAL_UDP_PORT 320 + +/* Define the TTL of PTP packets */ +#define NX_PTP_TIME_TO_LIVE 1 + +/* Define the IPv4 multicast address "224.0.1.129" */ +#define NX_PTP_IPV4_MULTICAST_ADDR IP_ADDRESS(224, 0, 1, 129) + +/* Define the IPv6 multicast address "ff0e::181" */ +#define NX_PTP_IPV6_MULTICAST_ADDR_SET(x) { \ + (x) -> nxd_ip_version = NX_IP_VERSION_V6; \ + (x) -> nxd_ip_address.v6[0] = 0xff0e0000UL; \ + (x) -> nxd_ip_address.v6[1] = 0; \ + (x) -> nxd_ip_address.v6[2] = 0; \ + (x) -> nxd_ip_address.v6[3] = 0x181; } + +/* Length of PTP message header */ +#define NX_PTP_MSG_HDR_LEN 34 + +/* Length of PTP messages (without header) */ +#define NX_PTP_MSG_ANNOUNCE_LEN 30 +#define NX_PTP_MSG_SYNC_LEN 10 +#define NX_PTP_MSG_FOLLOW_UP_LEN 10 +#define NX_PTP_MSG_DELAY_RESP_LEN 20 + +/* Length of PTP timestamp */ +#define NX_PTP_MSG_TIMESTAMP_LEN 10 + +/* Get version number */ +#define NX_PTP_MSG_VERSION(p_) ((p_)[1] & 0xf) + +/* Get domain number */ +#define NX_PTP_MSG_DOMAIN(p_) ((p_)[4]) + +/* Type of messages */ +#define NX_PTP_MSG_TYPE_SYNC 0 +#define NX_PTP_MSG_TYPE_DELAY_REQ 1 +#define NX_PTP_MSG_TYPE_FOLLOW_UP 8 +#define NX_PTP_MSG_TYPE_DELAY_RESP 9 +#define NX_PTP_MSG_TYPE_ANNOUNCE 11 + +/* Message flags */ +#define NX_PTP_MSG_HDR_FLAG_LEAP61 (1 << 0) +#define NX_PTP_MSG_HDR_FLAG_LEAP59 (1 << 1) +#define NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE (1 << 2) +#define NX_PTP_MSG_HDR_FLAG_TWO_STEP (1 << 9) + +/* Common Message Header */ +typedef struct NX_PTP_MSG_HEADER_STRUCT +{ + UCHAR transportSpecific; + UCHAR messageType; + UCHAR versionPTP; + UCHAR domainNumber; + USHORT messageLength; + USHORT flagField; + ULONG cFieldHigh; + ULONG cFieldLow; + UCHAR *sourcePortIdentity; + USHORT sequenceId; + UCHAR logMessageInterval; +} NX_PTP_MSG_HEADER; + +/* Get UTC offset from announce message */ +#define NX_PTP_MSG_UTC_OFFSET(p_) ((SHORT)((p_[10] << 8) | p_[11])) + +/* Macros for reading PTP packet fields */ +#define NX_PTP_RD16(p_, v_) { \ + USHORT t_; \ + t_ = *p_++; \ + t_ = (USHORT)(t_ << 8); \ + v_ = (USHORT)(t_ | *p_++); } + +#define NX_PTP_RD32(p_, v_) { \ + ULONG t_; \ + t_ = *p_++; \ + t_ <<= 8; \ + t_ |= *p_++; \ + t_ <<= 8; \ + t_ |= *p_++; \ + t_ <<= 8; \ + v_ = t_ |= *p_++; } + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_timestamp PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses timestamp field of a PTP message. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to PTP message */ +/* time_ptr Pointer to PTP time for output*/ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_msg_parse_timestamp(UCHAR *ptr, NX_PTP_TIME *time_ptr) +{ +ULONG nanoseconds = (ULONG)time_ptr -> nanosecond; + + NX_PTP_RD16(ptr, time_ptr -> second_high); + NX_PTP_RD32(ptr, time_ptr -> second_low); + NX_PTP_RD32(ptr, nanoseconds); + time_ptr -> nanosecond = (LONG)nanoseconds; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_hdr PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses the header of a PTP packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* hdr Parsed PTP header for output */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nxd_udp_packet_info_extract Extract UDP packet information*/ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_ptp_msg_parse_hdr(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_MSG_HEADER *hdr) +{ +UCHAR b; +UCHAR *ptr; +UINT len; +UINT status; +NXD_ADDRESS src_addr; +UINT interface_index; + +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) + { + + /* Chained packet is not supported */ + return(NX_NOT_SUPPORTED); + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* get pointer to PTP message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* get length of PTP message */ + len = packet_ptr -> nx_packet_length; + + /* check packet validity: */ + /* - length >= PTP header length */ + /* - PTP version */ + /* - domain number */ + if ((len < NX_PTP_MSG_HDR_LEN) || + (NX_PTP_MSG_VERSION(ptr) != NX_PTP_VERSION) || + (NX_PTP_MSG_DOMAIN(ptr) != client_ptr -> nx_ptp_client_domain)) + { + + /* discard invalid packet */ + return(NX_INVALID_PACKET); + } + + /* get info about sender and check packet validity: */ + /* - network interface */ + /* - IP version */ + status = nxd_udp_packet_info_extract(packet_ptr, &src_addr, NX_NULL, NX_NULL, &interface_index); + if ((status != NX_SUCCESS) || + (interface_index != client_ptr -> nx_ptp_client_interface_index) +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + || ((src_addr.nxd_ip_version == NX_IP_VERSION_V4) && + !client_ptr -> nx_ptp_client_ipv4_group_joined) || + ((src_addr.nxd_ip_version == NX_IP_VERSION_V6) && + !client_ptr -> nx_ptp_client_ipv6_group_joined) +#endif + ) + { + + /* discard invalid packet */ + return(NX_INVALID_PACKET); + } + + /* Save source address in listening state */ + if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING) + { + client_ptr -> nx_ptp_client_master_addr = src_addr; + } + + b = *ptr++; + hdr -> transportSpecific = b >> 4; + hdr -> messageType = b & 0xf; + b = *ptr++; + hdr -> versionPTP = b & 0xf; + NX_PTP_RD16(ptr, hdr -> messageLength); + hdr -> domainNumber = *ptr++; + ptr++; /* reserved */ + NX_PTP_RD16(ptr, hdr -> flagField); + NX_PTP_RD32(ptr, hdr -> cFieldHigh); + NX_PTP_RD32(ptr, hdr -> cFieldLow); + ptr += 4; /* reserved */ + hdr -> sourcePortIdentity = ptr; + ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + NX_PTP_RD16(ptr, hdr -> sequenceId); + ptr++; /* controlField - ignore */ + hdr -> logMessageInterval = *ptr; + + /* adjust message length */ + if (len > hdr -> messageLength) + { + if (hdr -> messageLength < NX_PTP_MSG_HDR_LEN) + { + + /* invalid length */ + return(NX_INVALID_PACKET); + } + len = hdr -> messageLength; + } + + /* Adjust packet. */ + packet_ptr -> nx_packet_prepend_ptr += NX_PTP_MSG_HDR_LEN; + packet_ptr -> nx_packet_length = len - NX_PTP_MSG_HDR_LEN; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_announce PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses PTP Announce message. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to PTP message */ +/* master_ptr Parsed PTP master for output */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_announce_received Process Announce message */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_msg_parse_announce(UCHAR *ptr, NX_PTP_CLIENT_MASTER *master) +{ + ptr += NX_PTP_MSG_TIMESTAMP_LEN + 2 + 1; /* originTimestamp, utcOffset, reserved */ + master -> nx_ptp_client_master_priority1 = *ptr++; + master -> nx_ptp_client_master_clock_class = *ptr++; + master -> nx_ptp_client_master_clock_accuracy = *ptr++; + NX_PTP_RD16(ptr, master -> nx_ptp_client_master_offset_scaled_log_variance); + master -> nx_ptp_client_master_priority2 = *ptr++; + master -> nx_ptp_client_master_grandmaster_identity = ptr; + ptr += NX_PTP_CLOCK_IDENTITY_SIZE; + NX_PTP_RD16(ptr, master -> nx_ptp_client_master_steps_removed); + master -> nx_ptp_client_master_time_source = *ptr; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_soft_clock_adjust PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adjusts the value of the soft PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* offset_ns Signed number of nanoseconds */ +/* to add to the PTP clock */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_callback Soft PTP clock */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_soft_clock_adjust(VOID *ptp_instance, LONG offset_ns) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; +TX_INTERRUPT_SAVE_AREA + + /* enforce min/max values of offset */ + if (offset_ns > NX_PTP_NANOSECONDS_PER_SEC) + { + offset_ns = NX_PTP_NANOSECONDS_PER_SEC; + } + else if (offset_ns < -NX_PTP_NANOSECONDS_PER_SEC) + { + offset_ns = -NX_PTP_NANOSECONDS_PER_SEC; + } + + /* add the number of nanosecond to the current time */ + TX_DISABLE + client_ptr -> nx_ptp_client_soft_clock.nanosecond += offset_ns; + if (client_ptr -> nx_ptp_client_soft_clock.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + client_ptr -> nx_ptp_client_soft_clock.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&client_ptr -> nx_ptp_client_soft_clock.second_high, + &client_ptr -> nx_ptp_client_soft_clock.second_low); + } + else if (client_ptr -> nx_ptp_client_soft_clock.nanosecond < 0) + { + client_ptr -> nx_ptp_client_soft_clock.nanosecond += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&client_ptr -> nx_ptp_client_soft_clock.second_high, + &client_ptr -> nx_ptp_client_soft_clock.second_low); + } + TX_RESTORE +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_timer_handler PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements the PTP client timer handler. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set Set PTP timer event */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX Timer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_timer_handler(ULONG ptp_instance) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; + + /* Update soft timer. */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE, + &client_ptr -> nx_ptp_client_soft_clock, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* set timer event */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_TIMER_EVENT, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_socket_receive_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is invoked when UDP packet is received. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to general socket */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set Set UDP receive event */ +/* */ +/* CALLED BY */ +/* */ +/* NetX UDP */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET *socket_ptr) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)(socket_ptr -> nx_udp_socket_reserved_ptr); + + /* set timer event */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_clock_adjust PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Adjust the PTP clock with the given offset */ +/* If the offset is greater than one second, the clock is updated, */ +/* otherwise it is adjusted with the number of nanoseconds. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* offset_ptr Pointer to time offset */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* _nx_ptp_client_utility_add64 Add two 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_clock_adjust(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *offset_ptr) +{ +NX_PTP_TIME current; + + if ((offset_ptr -> second_high == 0) && (offset_ptr -> second_low == 0)) + { + + /* offset less than 1s, adjust clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_ADJUST, offset_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + NX_PTP_DEBUG_PRINTF(("PTP: adjust clock %d ns\r\n", (INT)offset_ptr -> nanosecond)); + } + else + { + + /* offset greater than 1s, set new clock value */ + /* get current clock value */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, ¤t, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* add nanoseconds offset */ + current.nanosecond += offset_ptr -> nanosecond; + + /* ensure nanosecond field is in range 0-999999999 */ + if (current.nanosecond < 0) + { + current.nanosecond += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(¤t.second_high, ¤t.second_low); + } + else if (current.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + current.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(¤t.second_high, ¤t.second_low); + } + + /* add seconds offset */ + _nx_ptp_client_utility_add64(¤t.second_high, ¤t.second_low, + offset_ptr -> second_high, offset_ptr -> second_low); + + /* set new clock value */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, ¤t, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + NX_PTP_DEBUG_PRINTF(("PTP: set clock %u.%d\r\n", + (UINT)current.second_low, + (INT)current.nanosecond)); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_send_delay_req PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a PTP Delay Request message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_allocate Allocate a packet */ +/* nxd_udp_socket_source_send Send a UDP packet */ +/* nx_packet_release Release a packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_send_delay_req(NX_PTP_CLIENT *client_ptr) +{ +NX_PACKET *packet_ptr; +UINT status = NX_NOT_SUCCESSFUL; +UCHAR *ptr; +NXD_ADDRESS addr; +UINT addr_index = 0; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_IPV6_ADDRESS *ipv6_addr; +NX_IP *ip_ptr; +NX_INTERFACE *if_ptr; +#endif + + NX_PTP_DEBUG_PRINTF(("PTP: send DELAY_REQ\r\n")); + + /* allocate a packet from the pool */ + status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_NO_WAIT); + if (status != NX_SUCCESS) + { + /* Failed to allocate the packet */ + return; + } + + /* start of message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + +#define PTP_MSG_DELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN) +#define PTP_MSG_DELAY_REQ_ZERO1_LEN (1 + 2 + 8 + 4) + + /* write header */ + *ptr++ = NX_PTP_MSG_TYPE_DELAY_REQ; + *ptr++ = NX_PTP_VERSION; + *ptr++ = PTP_MSG_DELAY_REQ_TOTAL_LEN >> 8; + *ptr++ = (UCHAR)PTP_MSG_DELAY_REQ_TOTAL_LEN; + *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | client_ptr -> nx_ptp_client_domain; + memset(ptr, 0, PTP_MSG_DELAY_REQ_ZERO1_LEN); /* reserved/flags/correction/reserved */ + ptr += PTP_MSG_DELAY_REQ_ZERO1_LEN; + memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + client_ptr -> nx_ptp_client_delay_req_id++; + *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_delay_req_id >> 8); + *ptr++ = (UCHAR)client_ptr -> nx_ptp_client_delay_req_id; + *ptr++ = 0; /* control */ + *ptr++ = 0; /* XXX */ + + /* write timestamp (0) */ + memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN); + ptr += NX_PTP_MSG_TIMESTAMP_LEN; + + /* set final length of message */ + packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr); + packet_ptr -> nx_packet_append_ptr = ptr; + + /* set source and destination addresses */ +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr); + + /* Use first IPv6 address as source address. */ + ip_ptr = client_ptr -> nx_ptp_client_ip_ptr; + if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index]; + ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head; + if (ipv6_addr == NX_NULL) + { + + /* No available IPv6 address. */ + /* Release packet. */ + nx_packet_release(packet_ptr); + + /* Reset state. */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL; + + return; + } + addr_index = ipv6_addr -> nxd_ipv6_address_index; + } + else +#endif + { +#ifndef NX_DISABLE_IPV4 + addr.nxd_ip_version = NX_IP_VERSION_V4; + addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR; + addr_index = client_ptr -> nx_ptp_client_interface_index; +#endif + } + + /* Prepare timestamp for current packet */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_REQ_TS; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = packet_ptr; + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE, + &client_ptr -> nx_ptp_client_delay_ts, packet_ptr, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* Send delay request */ + status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket, + packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index); + if (status) + { + + /* release packet in case of error */ + nx_packet_release(packet_ptr); + + /* reset state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL; + + return; + } + + /* rearm delay req timer */ + client_ptr -> nx_ptp_client_delay_req_timer = NX_PTP_CLIENT_DELAY_REQ_INTERVAL; + client_ptr -> nx_ptp_client_delay_req_flag = 0; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_sync_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Sync message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ts_ptr Pointer to the timestamp */ +/* delivered by the Sync message*/ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_msg_parse_timestamp Parse timestamp field */ +/* _nx_ptp_client_send_delay_req Send delay request */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_sync_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr) +{ + NX_PTP_DEBUG_PRINTF(("PTP: rcv SYNC\r\n")); + + /* store Sync master timestamp */ + _nx_ptp_msg_parse_timestamp(ts_ptr, &client_ptr -> nx_ptp_client_sync); + + /* delay and offset determination */ + if (client_ptr -> nx_ptp_client_delay_req_flag) + { + + /* send delay request message */ + /* (delay_req_flag is cleared by this function) */ + _nx_ptp_client_send_delay_req(client_ptr); + } + + /* update Sync state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_delay_resp_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Delay Response message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ts_ptr Pointer to the timestamp */ +/* delivered by the Delay Resp */ +/* message */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_msg_parse_timestamp Parse timestamp field */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_delay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr) +{ +NX_PTP_TIME t4, a, b; +NX_PTP_CLIENT_SYNC sync; + + NX_PTP_DEBUG_PRINTF(("PTP: rcv DELAY_RESP\r\n")); + + /* + * The following timestamps are used for delay/offset determination: + * + * t1 = nx_ptp_client_sync + * t2 = nx_ptp_client_sync_ts + * t3 = nx_ptp_client_delay_ts + * t4 = timestamp in Delay_Resp message (ts_ptr) + * + * A = t2 - t1 + * B = t4 - t3 + * + * delay = (A + B) / 2 + * offset = (B - A) / 2 + */ + + /* check for valid timestamp t1 */ + if ((client_ptr -> nx_ptp_client_sync.second_low == 0) && + (client_ptr -> nx_ptp_client_sync.second_high == 0)) + { + return; + } + + /* get master clock timestamp */ + _nx_ptp_msg_parse_timestamp(ts_ptr, &t4); + + /* compute A = t2 - t1 */ + _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts, &client_ptr -> nx_ptp_client_sync, &a); + + /* compute B = t4 - t3 */ + _nx_ptp_client_utility_time_diff(&t4, &client_ptr -> nx_ptp_client_delay_ts, &b); + + /* compute offset = (B - A) / 2 */ + _nx_ptp_client_utility_time_diff(&b, &a, &a); + _nx_ptp_client_utility_time_div_by_2(&a); + +#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET) + if ((a.second_low == 0) && (a.second_high == 0)) + { + if ((a.nanosecond > -1000) && (a.nanosecond < 1000)) + { + printf("PTP: offset = %ld ns\n", a.nanosecond); + } + else if ((a.nanosecond > -1000000) && (a.nanosecond < 1000000)) + { + printf("PTP: offset = %ld us\n", a.nanosecond / 1000); + } + else + { + printf("PTP: offset = %ld ms\n", a.nanosecond / 1000000); + } + } + else + { + printf("PTP: offset > 1s\n"); + } +#endif + + /* add the time offset the client clock */ + _nx_ptp_client_clock_adjust(client_ptr, &a); + + /* set calibrated flag */ + if (!(client_ptr -> nx_ptp_client_sync_flags) & NX_PTP_CLIENT_SYNC_CALIBRATED) + { + + client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED; + + /* application callback */ + if (client_ptr -> nx_ptp_client_event_callback) + { + sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags; + sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset; + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + + /* update delay req state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_announce_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Announce message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* hdr Pointer to PTP header */ +/* ptr Pointer to PTP message */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_msg_parse_announce Parse Announce message */ +/* memcpy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_announce_received(NX_PTP_CLIENT *client_ptr, + NX_PTP_MSG_HEADER *hdr, + UCHAR *ptr) +{ +NX_PTP_CLIENT_SYNC sync; +NX_PTP_CLIENT_MASTER master; + + /* parse Sync information */ + sync.nx_ptp_client_sync_flags = 0; + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_UTC_REASONABLE; + } + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP59) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP59; + } + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP61) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP61; + } + sync.nx_ptp_client_sync_utc_offset = NX_PTP_MSG_UTC_OFFSET(ptr); + + /* check for new master */ + if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING) + { + + /* first announce message, save master clock parameters */ + client_ptr -> nx_ptp_client_sync_flags = sync.nx_ptp_client_sync_flags; + client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset; + memcpy(client_ptr -> nx_ptp_client_master_port_identity, hdr -> sourcePortIdentity, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + + /* wait for Sync message */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC; + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_delay_req_flag = 1; + + + /* call application callback */ + if (client_ptr -> nx_ptp_client_event_callback) + { + + /* parse annouce message */ + _nx_ptp_msg_parse_announce(ptr, &master); + master.nx_ptp_client_master_address = &(client_ptr -> nx_ptp_client_master_addr); + master.nx_ptp_client_master_port_identity = hdr -> sourcePortIdentity; + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER, &master, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + else + { + + /* check for UTC offset update or flags changes */ + if (((client_ptr -> nx_ptp_client_sync_flags & ~NX_PTP_CLIENT_SYNC_CALIBRATED) != + sync.nx_ptp_client_sync_flags) || + (client_ptr -> nx_ptp_client_utc_offset != sync.nx_ptp_client_sync_utc_offset)) + { + client_ptr -> nx_ptp_client_sync_flags = + (USHORT)((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) | + sync.nx_ptp_client_sync_flags); + client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset; + + /* call application callback */ + if ((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) && + (client_ptr -> nx_ptp_client_event_callback)) + { + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + } + + /* reset annouce timer */ + client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_process_event_packet PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes PTP packet received through event socket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_msg_parse_hdr Parse PTP header */ +/* memcmp Compare memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_thread_entry PTP thread entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_process_event_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ +NX_PTP_MSG_HEADER hdr; + + /* parse PTP message header */ + if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr)) + { + return; + } + + /* check origin of message */ + if (memcmp(&client_ptr -> nx_ptp_client_master_port_identity, + hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0) + { + + /* not from our master clock */ + return; + } + + if (hdr.messageType != NX_PTP_MSG_TYPE_SYNC) + { + return; + } + + if (((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_SYNC) && + (client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP)) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_SYNC_LEN)) + { + + /* not waiting for Sync or invalid message */ + return; + } + + /* retrieve timestamp of event message */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT, + &client_ptr -> nx_ptp_client_sync_ts, packet_ptr, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* two-step message? */ + if (hdr.flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP) + { + + /* wait for follow up message */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP; + client_ptr -> nx_ptp_client_sync_id = hdr.sequenceId; + } + else + { + + /* process Sync event */ + _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_process_general_packet PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes PTP packet received through general socket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_msg_parse_hdr Parse PTP header */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* _nx_ptp_client_announce_received Process Announce message */ +/* memcmp Compare memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_thread_entry PTP thread entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_process_general_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ +NX_PTP_MSG_HEADER hdr; + + /* parse PTP message header */ + if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr)) + { + return; + } + + /* check origin of message */ + if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_LISTENING) && + (memcmp(&client_ptr -> nx_ptp_client_master_port_identity, + hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)) + { + + /* not from our master clock */ + return; + } + + /* process ANNOUNCE message */ + if (hdr.messageType == NX_PTP_MSG_TYPE_ANNOUNCE) + { + if (packet_ptr -> nx_packet_length < NX_PTP_MSG_ANNOUNCE_LEN) + { + + /* invalid message */ + return; + } + + /* process announce message */ + _nx_ptp_client_announce_received(client_ptr, &hdr, packet_ptr -> nx_packet_prepend_ptr); + } + else if (hdr.messageType == NX_PTP_MSG_TYPE_FOLLOW_UP) + { + if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP) || + (client_ptr -> nx_ptp_client_sync_id != hdr.sequenceId) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_FOLLOW_UP_LEN)) + { + + /* not a follow up for a previous Sync or invalid message */ + return; + } + + /* process Sync message */ + _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } + else if (hdr.messageType == NX_PTP_MSG_TYPE_DELAY_RESP) + { + if ((client_ptr -> nx_ptp_client_delay_state != NX_PTP_CLIENT_DELAY_WAIT_RESP) || + (client_ptr -> nx_ptp_client_delay_req_id != hdr.sequenceId) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_DELAY_RESP_LEN) || + (memcmp(client_ptr -> nx_ptp_client_port_identity, + packet_ptr -> nx_packet_prepend_ptr + NX_PTP_MSG_TIMESTAMP_LEN, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)) + { + + /* not a delay_resp for a previous delay_req or invalid message */ + return; + } + + /* process delay response message */ + _nx_ptp_client_delay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_thread_entry PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements the PTP client processing thread. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* tx_event_flags_get Get PTP events */ +/* nx_udp_socket_receive Receive a UDP packet */ +/* nx_packet_release Release a packet */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_thread_entry(ULONG ptp_instance) +{ +TX_INTERRUPT_SAVE_AREA +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; +ULONG ptp_events; +UINT status; +NX_PACKET *packet_ptr = NX_NULL; +UCHAR packet_received; + + /* start in listening state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_announce_timeout = -1; + + /* main loop */ + for (;;) + { + + /* wait for message */ + status = tx_event_flags_get(&(client_ptr -> nx_ptp_client_events), + NX_PTP_CLIENT_ALL_EVENTS, TX_OR_CLEAR, + &ptp_events, TX_WAIT_FOREVER); + if (status != TX_SUCCESS) + { + + /* error while reading queue, abort thread */ + break; + } + + if (ptp_events & NX_PTP_CLIENT_STOP_EVENT) + { + + /* terminate thread */ + break; + } + + /* + * PTP Message Received + */ + if (ptp_events & NX_PTP_CLIENT_RX_EVENT) + { + + /* Loop to receive all packets. */ + for (;;) + { + packet_received = NX_FALSE; + if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_general_socket), + &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + _nx_ptp_client_process_general_packet(client_ptr, packet_ptr); + + /* Release packet. */ + nx_packet_release(packet_ptr); + packet_received = NX_TRUE; + } + + if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_event_socket), + &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + _nx_ptp_client_process_event_packet(client_ptr, packet_ptr); + + /* Release packet. */ + nx_packet_release(packet_ptr); + packet_received = NX_TRUE; + } + + if (packet_received == NX_FALSE) + { + + /* No more packets available. */ + break; + } + } + } + + /* + * Timer Event + */ + if (ptp_events & NX_PTP_CLIENT_TIMER_EVENT) + { + + /* announce messages timeout */ + if ((client_ptr -> nx_ptp_client_announce_timeout > 0) && + (--client_ptr -> nx_ptp_client_announce_timeout == 0)) + { + + /* no Annouce message received from master clock, back to listening state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_announce_timeout = -1; + + /* call handler */ + if (client_ptr -> nx_ptp_client_event_callback) + { + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_TIMEOUT, NX_NULL, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + + /* delay req interval timer */ + if ((client_ptr -> nx_ptp_client_delay_req_timer > 0) && + (--client_ptr -> nx_ptp_client_delay_req_timer == 0)) + { + + /* set flag */ + client_ptr -> nx_ptp_client_delay_req_flag = 1; + } + } + } + + /* set stopped state */ + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPED; + TX_RESTORE +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client create service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ip_ptr Pointer to client IP instance */ +/* interface_index Index of PTP network interface*/ +/* packet_pool_ptr Pointer to client packet pool */ +/* thread_priority Priority of PTP thread */ +/* thread_stack Pointer to thread stack */ +/* stack_size Size of thread stack */ +/* clock_callback PTP clock callback */ +/* clock_callback_data Data for the clock callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_create Actual create service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || + (thread_stack == NX_NULL) || (stack_size == 0) || (clock_callback == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for invalid network interface input. */ + if (interface_index >= NX_MAX_PHYSICAL_INTERFACES) + { + return(NX_INVALID_INTERFACE); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return _nx_ptp_client_create(client_ptr, ip_ptr, interface_index, packet_pool_ptr, thread_priority, + thread_stack, stack_size, clock_callback, clock_callback_data); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ip_ptr Pointer to client IP instance */ +/* interface_index Index of PTP network interface*/ +/* packet_pool_ptr Pointer to client packet pool */ +/* thread_priority Priority of PTP thread */ +/* thread_stack Pointer to thread stack */ +/* stack_size Size of thread stack */ +/* clock_callback PTP clock callback */ +/* clock_callback_data Data for the clock callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* memset Reset memory */ +/* [clock_callback] Initialize clock */ +/* tx_event_flags_create Create PTP event flags */ +/* tx_event_flags_delete Delete PTP event flags */ +/* nx_udp_socket_create Create a UDP socket */ +/* nx_udp_socket_delete Delete a UDP socket */ +/* nx_udp_socket_receive_notify Set UDP receive notify */ +/* tx_timer_create Create a timer */ +/* tx_timer_delete Delete a timer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data) +{ +UINT status; + + /* Null the members of NX_PTP_CLIENT. */ + memset(client_ptr, 0, sizeof(NX_PTP_CLIENT)); + + /* Set the Client ID to indicate the PTP client thread is ready. */ + client_ptr -> nx_ptp_client_id = NX_PTP_CLIENT_ID; + + /* Set the IP instance. */ + client_ptr -> nx_ptp_client_ip_ptr = ip_ptr; + + /* Set the PTP network interface. */ + client_ptr -> nx_ptp_client_interface_index = interface_index; + + /* Set the packet pool, check for minimal packet size requirement. */ + if (packet_pool_ptr -> nx_packet_pool_payload_size < + (NX_UDP_PACKET + NX_PTP_CLIENT_PACKET_DATA_SIZE)) + { + return(NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD); + } + client_ptr -> nx_ptp_client_packet_pool_ptr = packet_pool_ptr; + + /* Initialize callback function. */ + status = clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_INIT, NX_NULL, NX_NULL, clock_callback_data); + if (status) + { + + /* Fail to initialize clock in callback function. */ + return(NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE); + } + + /* Set the PTP clock callback */ + client_ptr -> nx_ptp_client_clock_callback = clock_callback; + client_ptr -> nx_ptp_client_clock_callback_data = clock_callback_data; + + /* create the internal PTP event flag object. */ + status = tx_event_flags_create(&(client_ptr -> nx_ptp_client_events), "NetX PTP event flag"); + if (status != TX_SUCCESS) + { + return(status); + } + + /* create the general socket */ + status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_general_socket, + "NetX PTP Client general socket", NX_IP_NORMAL, + NX_DONT_FRAGMENT, NX_PTP_TIME_TO_LIVE, + NX_PTP_CLIENT_MAX_QUEUE_DEPTH); + if (status != NX_SUCCESS) + { + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + client_ptr -> nx_ptp_client_general_socket.nx_udp_socket_reserved_ptr = client_ptr; + nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_general_socket, _nx_ptp_client_socket_receive_notify); + + /* create the event socket */ + status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_event_socket, + "NetX PTP Client event socket", NX_IP_NORMAL, NX_DONT_FRAGMENT, + NX_PTP_TIME_TO_LIVE, + NX_PTP_CLIENT_MAX_QUEUE_DEPTH); + if (status != NX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + client_ptr -> nx_ptp_client_event_socket.nx_udp_socket_reserved_ptr = client_ptr; + nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_event_socket, _nx_ptp_client_socket_receive_notify); + + /* create the timer */ + status = tx_timer_create(&client_ptr -> nx_ptp_client_timer, + "NetX PTP Client timer", + _nx_ptp_client_timer_handler, + (ULONG)client_ptr, + TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND, + TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND, + TX_NO_ACTIVATE); + if (status != TX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + + /* create the Client thread */ + status = tx_thread_create(&client_ptr -> nx_ptp_client_thread, + "NetX PTP Client", _nx_ptp_client_thread_entry, + (ULONG)client_ptr, thread_stack, stack_size, + thread_priority, thread_priority, + NX_PTP_CLIENT_THREAD_TIME_SLICE, TX_DONT_START); + if (status != TX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket); + tx_timer_delete(&client_ptr -> nx_ptp_client_timer); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + + /* return Success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client delete service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_delete Actual delete service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr) +{ + + /* Check input parameters. */ + if (client_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_delete(client_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_stop Stop PTP service */ +/* tx_thread_suspend Suspend PTP thread */ +/* tx_thread_terminate Terminate PTP thread */ +/* tx_thread_delete Delete PTP thread */ +/* tx_event_flags_delete Delete PTP event flags */ +/* nx_udp_socket_delete Delete a UDP socket */ +/* tx_timer_delete Delete a timer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr) +{ + + /* Ensure the Client is stopped */ + _nx_ptp_client_stop(client_ptr); + + /* Suspend the Client thread. */ + tx_thread_suspend(&client_ptr -> nx_ptp_client_thread); + + /* Terminate Client thread. */ + tx_thread_terminate(&client_ptr -> nx_ptp_client_thread); + + /* Delete Client thread. */ + tx_thread_delete(&client_ptr -> nx_ptp_client_thread); + + /* Delete the timer */ + tx_timer_delete(&client_ptr -> nx_ptp_client_timer); + + /* Delete the general socket */ + nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket); + + /* Delete the event socket */ + nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket); + + /* Delete the event flag */ + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_start PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client start service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* client_port_identity_ptr Pointer to client port and */ +/* identity */ +/* client_port_identity_length Length of client port and */ +/* identity */ +/* domain PTP clock domain */ +/* transport_specific Transport specific */ +/* event_callback Event callback */ +/* event_callback_data Data for the event callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_start Actual start service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || + ((client_port_identity_ptr == NX_NULL) && (client_port_identity_length != 0)) || + ((client_port_identity_ptr != NX_NULL) && (client_port_identity_length != NX_PTP_CLOCK_PORT_IDENTITY_SIZE))) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_start(client_ptr, client_port_identity_ptr, client_port_identity_length, + domain, transport_specific, event_callback, event_callback_data)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_start PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* client_port_identity_ptr Pointer to client port and */ +/* identity */ +/* client_port_identity_length Length of client port and */ +/* identity */ +/* domain PTP clock domain */ +/* transport_specific Transport specific */ +/* event_callback Event callback */ +/* event_callback_data Data for the event callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_suspend Suspend PTP thread */ +/* tx_thread_terminate Terminate PTP thread */ +/* tx_thread_reset Reset PTP thread */ +/* tx_thread_resume Resume PTP thread */ +/* memcpy Copy memory */ +/* nx_ip_interface_physical_address_get Get physical address */ +/* nx_udp_socket_bind Bind UDP port */ +/* nx_ipv4_multicast_interface_join Join IPv4 multicast group */ +/* nxd_ipv6_multicast_interface_join Join IPv6 multicast group */ +/* tx_timer_activate Activate timer */ +/* _nx_ptp_client_stop Stop PTP service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; +UINT status; +ULONG msw, lsw; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_ADDRESS maddr; +#endif + + NX_PARAMETER_NOT_USED(client_port_identity_length); + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + if (state == NX_PTP_CLIENT_THREAD_IDLE) + { + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_RUNNING; + } + TX_RESTORE + if (state != NX_PTP_CLIENT_THREAD_IDLE) + { + + /* Client is already running */ + return(NX_PTP_CLIENT_ALREADY_STARTED); + } + + /* ensure the thread is terminated */ + tx_thread_suspend(&client_ptr -> nx_ptp_client_thread); + tx_thread_terminate(&client_ptr -> nx_ptp_client_thread); + + /* save the client parameters */ + client_ptr -> nx_ptp_client_domain = (UCHAR)domain; + client_ptr -> nx_ptp_client_transport_specific = (UCHAR)transport_specific; + client_ptr -> nx_ptp_client_event_callback = event_callback; + client_ptr -> nx_ptp_client_event_callback_data = event_callback_data; + + /* reset and resume the thread */ + status = tx_thread_reset(&client_ptr -> nx_ptp_client_thread); + if (status != TX_SUCCESS) + { + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE; + TX_RESTORE + + return(status); + } + tx_thread_resume(&client_ptr -> nx_ptp_client_thread); + + /* set the client port and identity */ + if (client_port_identity_ptr != NX_NULL) + { + + /* copy provided identifier */ + memcpy(client_ptr -> nx_ptp_client_port_identity, client_port_identity_ptr, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + } + else + { + + /* get MAC address of interface */ + status = nx_ip_interface_physical_address_get(client_ptr -> nx_ptp_client_ip_ptr, + client_ptr -> nx_ptp_client_interface_index, + &msw, &lsw); + if (status == TX_SUCCESS) + { + /* convert 48-bit MAC address to 64-bit EUI */ + client_ptr -> nx_ptp_client_port_identity[0] = (UCHAR)(msw >> 8); + client_ptr -> nx_ptp_client_port_identity[1] = (UCHAR)msw; + client_ptr -> nx_ptp_client_port_identity[2] = (UCHAR)(lsw >> 24); + client_ptr -> nx_ptp_client_port_identity[3] = 0xff; + client_ptr -> nx_ptp_client_port_identity[4] = 0xfe; + client_ptr -> nx_ptp_client_port_identity[5] = (UCHAR)(lsw >> 16); + client_ptr -> nx_ptp_client_port_identity[6] = (UCHAR)(lsw >> 8); + client_ptr -> nx_ptp_client_port_identity[7] = (UCHAR)lsw; + + /* set default port number (1) */ + client_ptr -> nx_ptp_client_port_identity[8] = 0; + client_ptr -> nx_ptp_client_port_identity[9] = 1; + } + } + + /* bind the general socket */ + if (status == TX_SUCCESS) + { + status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket, + NX_PTP_GENERAL_UDP_PORT, NX_NO_WAIT); + } + + /* bind the event socket */ + if (status == TX_SUCCESS) + { + status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket, + NX_PTP_EVENT_UDP_PORT, NX_NO_WAIT); + } + + /* join the multicast groups */ + if (status == TX_SUCCESS) + { + status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr, + NX_PTP_IPV4_MULTICAST_ADDR, + client_ptr -> nx_ptp_client_interface_index); + if (status == TX_SUCCESS) + { + client_ptr -> nx_ptp_client_ipv4_group_joined = NX_TRUE; + } + } +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (status == TX_SUCCESS) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr); + status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr, + &maddr, client_ptr -> nx_ptp_client_interface_index); + if (status == TX_SUCCESS) + { + client_ptr -> nx_ptp_client_ipv6_group_joined = NX_TRUE; + } + else if ((status == NX_NOT_SUPPORTED) && (client_ptr -> nx_ptp_client_ipv4_group_joined)) + { + + /* IPv6 not enabled, use IPv4 only */ + status = TX_SUCCESS; + } + } +#endif + + /* activate the Client timer */ + if (status == TX_SUCCESS) + { + + /* activate the timer */ + status = tx_timer_activate(&client_ptr -> nx_ptp_client_timer); + } + + /* stop the client thread in case of error */ + if (status != TX_SUCCESS) + { + _nx_ptp_client_stop(client_ptr); + + /* return failure */ + return(status); + } + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_stop PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client stop service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_stop Actual stop service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr) +{ + + /* Check input parameters. */ + if (client_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_stop(client_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_stop PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_timer_deactivate Deactivate timer */ +/* nx_udp_socket_unbind Unbind UDP port */ +/* nx_ipv4_multicast_interface_leave Leave IPv4 multicast group */ +/* nxd_ipv6_multicast_interface_leave Leave IPv6 multicast group */ +/* tx_event_flags_set Set PTP timer event */ +/* tx_thread_sleep Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_ADDRESS maddr; +#endif + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + if (state == NX_PTP_CLIENT_THREAD_RUNNING) + { + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPING; + } + TX_RESTORE + if ((state != NX_PTP_CLIENT_THREAD_RUNNING) && + (state != NX_PTP_CLIENT_THREAD_STOPPED)) + { + + /* Client is not running */ + return(NX_PTP_CLIENT_NOT_STARTED); + } + + /* deactivate the timer */ + tx_timer_deactivate(&client_ptr -> nx_ptp_client_timer); + + /* unbind the sockets */ + nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket); + + /* leave multicast groups */ + if (client_ptr -> nx_ptp_client_ipv4_group_joined) + { + nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr, + NX_PTP_IPV4_MULTICAST_ADDR, + client_ptr -> nx_ptp_client_interface_index); + client_ptr -> nx_ptp_client_ipv4_group_joined = NX_FALSE; + } +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (client_ptr -> nx_ptp_client_ipv6_group_joined) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr); + nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr, + &maddr, client_ptr -> nx_ptp_client_interface_index); + client_ptr -> nx_ptp_client_ipv6_group_joined = NX_FALSE; + } +#endif + + /* send STOP message */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_STOP_EVENT, TX_OR); + + /* wait for thread termination */ + while (state != NX_PTP_CLIENT_THREAD_STOPPED) + { + tx_thread_sleep(1); + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + TX_RESTORE + } + + /* set Idle state */ + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE; + TX_RESTORE + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_time_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time get service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_time_get Actual time get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_time_get(client_ptr, time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_time_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the current value of the PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Get the current PTP clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, + time_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_time_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time set service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_time_set Actual time set service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_time_set(client_ptr, time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_time_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the initial time of the PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + TX_RESTORE + + if (state != NX_PTP_CLIENT_THREAD_IDLE) + { + + /* Cannot set the clock when the client is running */ + return(NX_PTP_CLIENT_ALREADY_STARTED); + } + + /* Set the current PTP clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, + time_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_master_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP master info get service. */ +/* */ +/* INPUT */ +/* */ +/* master_ptr Pointer to PTP master clock */ +/* address Address of master clock */ +/* port_identity PTP master port and identity */ +/* port_identity_length Length of PTP master port and */ +/* identity */ +/* priority1 Priority1 of PTP master clock */ +/* priority2 Priority2 of PTP master clock */ +/* clock_class Class of PTP master clock */ +/* clock_accuracy Accuracy of PTP master clock */ +/* clock_variance Variance of PTP master clock */ +/* grandmaster_identity Identity of grandmaster clock */ +/* grandmaster_identity_length Length of grandmaster Identity*/ +/* steps_removed Steps removed from PTP header */ +/* time_source The source of timer used by */ +/* grandmaster clock */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_master_info_get Actual master info get service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source) +{ + if (master_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + return(_nx_ptp_client_master_info_get(master_ptr, address, port_identity, port_identity_length, priority1, + priority2, clock_class, clock_accuracy, clock_variance, grandmaster_identity, + grandmaster_identity_length, steps_removed, time_source)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_master_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets information of master clock. */ +/* */ +/* INPUT */ +/* */ +/* master_ptr Pointer to PTP master clock */ +/* address Address of master clock */ +/* port_identity PTP master port and identity */ +/* port_identity_length Length of PTP master port and */ +/* identity */ +/* priority1 Priority1 of PTP master clock */ +/* priority2 Priority2 of PTP master clock */ +/* clock_class Class of PTP master clock */ +/* clock_accuracy Accuracy of PTP master clock */ +/* clock_variance Variance of PTP master clock */ +/* grandmaster_identity Identity of grandmaster clock */ +/* grandmaster_identity_length Length of grandmaster Identity*/ +/* steps_removed Steps removed from PTP header */ +/* time_source The source of timer used by */ +/* grandmaster clock */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source) +{ + + /* Set master information when the output pointer is provided. */ + if (address) + { + *address = *(master_ptr -> nx_ptp_client_master_address); + } + + if (port_identity && port_identity_length) + { + *port_identity = master_ptr -> nx_ptp_client_master_port_identity; + *port_identity_length = NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + } + + if (priority1) + { + *priority1 = master_ptr -> nx_ptp_client_master_priority1; + } + + if (priority2) + { + *priority2 = master_ptr -> nx_ptp_client_master_priority2; + } + + if (clock_class) + { + *clock_class = master_ptr -> nx_ptp_client_master_clock_class; + } + + if (clock_accuracy) + { + *clock_accuracy = master_ptr -> nx_ptp_client_master_clock_accuracy; + } + + if (clock_variance) + { + *clock_variance = master_ptr -> nx_ptp_client_master_offset_scaled_log_variance; + } + + if (grandmaster_identity && grandmaster_identity_length) + { + *grandmaster_identity = master_ptr -> nx_ptp_client_master_grandmaster_identity; + *grandmaster_identity_length = NX_PTP_CLOCK_IDENTITY_SIZE; + } + + if (steps_removed) + { + *steps_removed = master_ptr -> nx_ptp_client_master_steps_removed; + } + + if (time_source) + { + *time_source = master_ptr -> nx_ptp_client_master_time_source; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_sync_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP Sync get service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* flags Flags in Sync message */ +/* utc_offset Offset between TAI and UTC */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_info_get Actual Sync info get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset) +{ + if (sync_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + return(_nx_ptp_client_sync_info_get(sync_ptr, flags, utc_offset)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_sync_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets information of Sync message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* flags Flags in Sync message */ +/* utc_offset Offset between TAI and UTC */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset) +{ + + /* Set SYNC information when the output pointer is provided. */ + if (flags) + { + *flags = sync_ptr -> nx_ptp_client_sync_flags; + } + + if (utc_offset) + { + *utc_offset = sync_ptr -> nx_ptp_client_sync_utc_offset; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_packet_timestamp_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function notifies the PTP packet is transmitted with timestamp.*/ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* timestamp_ptr Pointer to timestamp */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr) +{ + + /* get timestamp of previous delay_req message */ + if (client_ptr && + (client_ptr -> nx_ptp_client_delay_state == NX_PTP_CLIENT_DELAY_WAIT_REQ_TS) && + (client_ptr -> nx_ptp_client_delay_req_packet_ptr == packet_ptr)) + { + + /* store timestamp */ + client_ptr -> nx_ptp_client_delay_ts = *timestamp_ptr; + + /* update state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_RESP; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_soft_clock_callback PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements soft PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* operation PTP clock operation */ +/* time_ptr Pointer to timestamp */ +/* packet_ptr Pointer to PTP packet */ +/* callback_data Pointer to callback data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* PTP internal */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data) +{ +TX_INTERRUPT_SAVE_AREA + + NX_PARAMETER_NOT_USED(callback_data); + + switch (operation) + { + + /* Nothing to do for soft initialization. */ + case NX_PTP_CLIENT_CLOCK_INIT: + break; + + /* Set clock. */ + case NX_PTP_CLIENT_CLOCK_SET: + TX_DISABLE + client_ptr -> nx_ptp_client_soft_clock = *time_ptr; + TX_RESTORE + break; + + /* Extract timestamp from packet. + For soft implementation, simply fallthrough and return current timestamp. */ + case NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT: + + /* Get clock. */ + case NX_PTP_CLIENT_CLOCK_GET: + TX_DISABLE + *time_ptr = client_ptr -> nx_ptp_client_soft_clock; + TX_RESTORE + break; + + /* Adjust clock. */ + case NX_PTP_CLIENT_CLOCK_ADJUST: + _nx_ptp_client_soft_clock_adjust(client_ptr, time_ptr -> nanosecond); + break; + + /* Prepare timestamp for current packet. + For soft implementation, simply notify current timestamp. */ + case NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE: + _nx_ptp_client_packet_timestamp_notify(client_ptr, packet_ptr, &(client_ptr -> nx_ptp_client_soft_clock)); + break; + + /* Update soft timer. */ + case NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE: + TX_DISABLE + + /* increment the nanosecond field of the software clock */ + time_ptr -> nanosecond += + (LONG)(NX_PTP_NANOSECONDS_PER_SEC / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND); + + /* update the second field */ + if (time_ptr -> nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + time_ptr -> nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&(time_ptr -> second_high), + &(time_ptr -> second_low)); + } + TX_RESTORE + break; + + default: + return(NX_PTP_PARAM_ERROR); + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_utility_time_diff PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time difference service. */ +/* */ +/* INPUT */ +/* */ +/* time1_ptr Pointer to first PTP time */ +/* time2_ptr Pointer to second PTP time */ +/* result_ptr Pointer to result time1-time2 */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_time_diff Actual time difference service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr) +{ + + /* Check input parameters. */ + if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_utility_time_diff(time1_ptr, time2_ptr, result_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_time_diff PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function computes the difference between two PTP times. */ +/* */ +/* INPUT */ +/* */ +/* time1_ptr Pointer to first PTP time */ +/* time2_ptr Pointer to second PTP time */ +/* result_ptr Pointer to result time1-time2 */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_sub64 Subtracts two 64-bit numbers */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr) +{ +LONG sec_hi; +ULONG sec_lo; +LONG ns; + + /* compute difference of seconds */ + sec_hi = time1_ptr -> second_high; + sec_lo = time1_ptr -> second_low; + _nx_ptp_client_utility_sub64(&sec_hi, &sec_lo, time2_ptr -> second_high, + time2_ptr -> second_low); + + /* compute difference of nanoseconds */ + /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */ + ns = time1_ptr -> nanosecond - time2_ptr -> nanosecond; + + /* keep nanoseconds in range +/-0-999999999 */ + if (ns <= -NX_PTP_NANOSECONDS_PER_SEC) + { + ns += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo); + } + else if (ns >= NX_PTP_NANOSECONDS_PER_SEC) + { + ns -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo); + } + + /* ensure the nanoseconds field has same sign as seconds field */ + if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0))) + { + /* positive number of seconds */ + if (ns < 0) + { + ns += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo); + } + } + else if (sec_hi < 0) + { + /* negative number of seconds */ + if (ns > 0) + { + ns -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo); + } + } + + /* return result time */ + result_ptr -> second_high = sec_hi; + result_ptr -> second_low = sec_lo; + result_ptr -> nanosecond = ns; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_utility_convert_time_to_date PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time conversion service. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* offset signed second offset to add */ +/* the PTP time */ +/* date_time_ptr Pointer to resulting date */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_convert_time_to_date */ +/* Actual time conversion service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr) +{ + + /* Check input parameters. */ + if ((time_ptr == NX_NULL) || (date_time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_utility_convert_time_to_date(time_ptr, offset, date_time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_convert_time_to_date PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a PTP time to a UTC date and time. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* offset Signed second offset to add */ +/* the PTP time */ +/* date_time_ptr Pointer to resulting date */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_add64 Add two 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr) +{ +#define IS_LEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) +#define SECS_PER_MINUTE 60 +#define SECS_PER_HOUR (60 * SECS_PER_MINUTE) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) +LONG secs_high; +ULONG secs_low; +UINT year, month, day, hour, minute; +ULONG secs_per_year, secs_per_month; +ULONG weekday; +UINT is_leap; + + /* get number of seconds */ + secs_high = time_ptr -> second_high; + secs_low = time_ptr -> second_low; + + /* add local time offset */ + if (offset != 0) + { + _nx_ptp_client_utility_add64(&secs_high, &secs_low, offset < 0 ? -1 : 0, (ULONG)offset); + } + if (secs_high < 0) + { + + /* invalid negative time */ + return(NX_PTP_PARAM_ERROR); + } + + /* determine the current year from Epoch (January 1, 1970) */ + year = 1970; + secs_per_year = 365 * SECS_PER_DAY; + is_leap = 0; + weekday = 4; /* thursday */ + while ((secs_high > 0) || (secs_low >= secs_per_year)) + { + if (secs_low < secs_per_year) + { + secs_high--; + } + secs_low -= secs_per_year; + weekday += is_leap ? 366 : 365; + year++; + is_leap = IS_LEAP(year) ? 1 : 0; + secs_per_year = is_leap ? 366 * SECS_PER_DAY : 365 * SECS_PER_DAY; + } + /* compute day of the week from remaining seconds */ + weekday = (weekday + secs_low / SECS_PER_DAY) % 7; + + /* determine current month */ + month = 1; + secs_per_month = 31 * SECS_PER_DAY; + while (secs_low >= secs_per_month) + { + secs_low -= secs_per_month; + month++; + if (month == 2) + { + + /* february */ + secs_per_month = is_leap ? 29 * SECS_PER_DAY : 28 * SECS_PER_DAY; + } + else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) + { + + /* april, june, september, november */ + secs_per_month = 30 * SECS_PER_DAY; + } + else + { + + /* the other months */ + secs_per_month = 31 * SECS_PER_DAY; + } + } + + /* determine current day of the month */ + day = secs_low / SECS_PER_DAY; + secs_low -= day * SECS_PER_DAY; + + /* determine current hour */ + hour = secs_low / SECS_PER_HOUR; + secs_low -= hour * SECS_PER_HOUR; + + /* determine current minute */ + minute = secs_low / SECS_PER_MINUTE; + secs_low -= minute * SECS_PER_MINUTE; + + /* return date */ + date_time_ptr -> year = year; + date_time_ptr -> month = (UCHAR)month; + date_time_ptr -> day = (UCHAR)(day + 1); + date_time_ptr -> hour = (UCHAR)hour; + date_time_ptr -> minute = (UCHAR)minute; + date_time_ptr -> second = (UCHAR)secs_low; + date_time_ptr -> weekday = (UCHAR)weekday; + date_time_ptr -> nanosecond = (ULONG)time_ptr -> nanosecond; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_add64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds two 64-bit numbers: A = A + B. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* b_hi higher 32-bit of B */ +/* b_lo lower 32-bit of B */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_convert_time_to_date */ +/* Convert time to date */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo) +{ +LONG r_hi; +ULONG r_lo; + + r_hi = *a_hi + b_hi; + r_lo = *a_lo + b_lo; + if (r_lo < *a_lo) + { + r_hi++; /* add carry */ + } + *a_hi = r_hi; + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_sub64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function substracts two 64-bit numbers: A = A - B. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* b_hi higher 32-bit of B */ +/* b_lo lower 32-bit of B */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo) +{ +LONG r_hi; +ULONG r_lo; + + r_hi = *a_hi - b_hi; + r_lo = *a_lo - b_lo; + if (*a_lo < b_lo) + { + r_hi--; /* substract carry */ + } + *a_hi = r_hi; + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_inc64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function increments a 64-bit number: A = A + 1. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* _nx_ptp_client_soft_clock_callback Soft PTP clock */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo) +{ +ULONG r_lo; + + r_lo = *a_lo + 1; + if (r_lo == 0) + { + *a_hi = *a_hi + 1; /* add carry */ + } + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_dec64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function decrements a 64-bit number: A = A - 1. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo) +{ +ULONG r_lo; + + r_lo = *a_lo; + if (r_lo == 0) + { + *a_hi = *a_hi - 1; /* substract carry */ + } + *a_lo = r_lo - 1; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_neg64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the sign of a 64-bit number: A = -A. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo) +{ +LONG r_hi; + + r_hi = -*a_hi; + if (*a_lo != 0) + { + r_hi--; /* substract carry */ + } + *a_hi = r_hi; + *a_lo = -*a_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_time_div_by_2 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function divides a PTP time by 2. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_neg64 Change the sign of number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr) +{ +UINT neg; +LONG sec_hi; +ULONG sec_lo; +LONG ns; + + /* get current time value */ + sec_hi = time_ptr -> second_high; + sec_lo = time_ptr -> second_low; + ns = time_ptr -> nanosecond; + + /* implement division on unsigned values */ + if ((sec_hi < 0) || (ns < 0)) + { + _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo); + ns = -ns; + neg = 1; + } + else + { + neg = 0; + } + + /* divide nanoseconds by two */ + ns >>= 1; + if (sec_lo & 1) + { + + /* add rest of seconds division */ + ns += 500000000L; + } + + /* divide seconds by two */ + sec_lo >>= 1; + if (sec_hi & 1) + { + sec_lo |= 0x80000000UL; + } + sec_hi >>= 1; + + /* restore sign */ + if (neg) + { + _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo); + ns = -ns; + } + + /* return result */ + time_ptr -> second_high = sec_hi; + time_ptr -> second_low = sec_lo; + time_ptr -> nanosecond = ns; +} diff --git a/addons/ptp/nxd_ptp_client.h b/addons/ptp/nxd_ptp_client.h new file mode 100644 index 00000000..3524b860 --- /dev/null +++ b/addons/ptp/nxd_ptp_client.h @@ -0,0 +1,482 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX PTP Client Component */ +/** */ +/** Precision Time Protocol (PTP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nxd_ptp_client.h PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX Precision Time Protocol (PTP) */ +/* Client component, including all data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NXD_PTP_CLIENT_H +#define NXD_PTP_CLIENT_H + + +/* Include NetX and ThreadX definitions */ + +#include "nx_api.h" + + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + + +/* PTP Client configurable options. */ + + +/* Set the client thread time slice. */ + +#ifndef NX_PTP_CLIENT_THREAD_TIME_SLICE +#define NX_PTP_CLIENT_THREAD_TIME_SLICE TX_NO_TIME_SLICE +#endif + + +/* Define the PTP Client ID */ + +#define NX_PTP_CLIENT_ID 0x50545001UL + + +/* Define the PTP client internal timer frequency */ + +#ifndef NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND +#define NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND 10 +#endif + + +/* Define the maximum number of missing Announce packets before timeout */ + +#ifndef NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT +#define NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT 3 +#endif + + +/* Define the time interval between successive Announce packet, expressed as log 2. + This value should be uniform throughout a domain. The default value is 1=2s. */ + +#ifndef NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL +#define NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL 1 +#endif + + +/* Define the interval for sending Delay request packets */ + +#ifndef NX_PTP_CLIENT_DELAY_REQ_INTERVAL +#define NX_PTP_CLIENT_DELAY_REQ_INTERVAL (2 * NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND) +#endif + + +/* Set maximum queue depth for client socket.*/ + +#ifndef NX_PTP_CLIENT_MAX_QUEUE_DEPTH +#define NX_PTP_CLIENT_MAX_QUEUE_DEPTH 5 +#endif + +/* Define the maximum size of a PTP message */ + +#define NX_PTP_CLIENT_PACKET_DATA_SIZE 64 + +/* Define Announce receipt timeout expire value */ +#define NX_PTP_CLIENT_ANNOUNCE_EXPIRATION (NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT * \ + (1 << NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL) * \ + NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND) + + +/* Define a PTP Time */ + +typedef struct NX_PTP_TIME_STRUCT +{ + /* The MSB of the number of seconds */ + LONG second_high; + + /* The LSB of the number of seconds */ + ULONG second_low; + + /* The number of nanoseconds */ + LONG nanosecond; +} NX_PTP_TIME; + + +/* Define the PTP Date Time structure. */ + +typedef struct NX_PTP_DATE_TIME_STRUCT +{ + UINT year; + UCHAR month; + UCHAR day; + UCHAR hour; + UCHAR minute; + UCHAR second; + UCHAR weekday; + ULONG nanosecond; +} NX_PTP_DATE_TIME; + + +/* Internal PTP error processing codes. */ + +#define NX_PTP_ERROR_CONSTANT 0xD00 +/* Client side errors. */ +#define NX_PTP_CLIENT_NOT_STARTED (NX_PTP_ERROR_CONSTANT | 0x01) /* PTP Client task is not running */ +#define NX_PTP_CLIENT_ALREADY_STARTED (NX_PTP_ERROR_CONSTANT | 0x02) /* PTP Client task is already running */ +#define NX_PTP_PARAM_ERROR (NX_PTP_ERROR_CONSTANT | 0x03) /* Invalid non pointer parameter. */ +#define NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD (NX_PTP_ERROR_CONSTANT | 0x04) /* Client not properly initialized to receive time data. */ +#define NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE (NX_PTP_ERROR_CONSTANT | 0x05) /* PTP clock callback returns error. */ + + +/* PTP Protocol Definitions */ + +/* Define the size of the PTP Clock Identity field */ +#define NX_PTP_CLOCK_IDENTITY_SIZE 8 + +/* Define the size of the PTP Clock Port and Identity field */ +#define NX_PTP_CLOCK_PORT_IDENTITY_SIZE (NX_PTP_CLOCK_IDENTITY_SIZE + 2) + + +/* PTP event callback */ + +struct NX_PTP_CLIENT_STRUCT; + +typedef UINT (*NX_PTP_CLIENT_EVENT_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT event, + VOID *event_data, VOID *callback_data); + +#define NX_PTP_CLIENT_EVENT_MASTER 0 +#define NX_PTP_CLIENT_EVENT_SYNC 1 +#define NX_PTP_CLIENT_EVENT_TIMEOUT 2 + + +/* PTP clock callback operations */ + +typedef UINT (*NX_PTP_CLIENT_CLOCK_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, VOID *callback_data); + +#define NX_PTP_CLIENT_CLOCK_INIT 0 /* Initialization */ +#define NX_PTP_CLIENT_CLOCK_SET 1 /* Set the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_GET 2 /* Get the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_ADJUST 3 /* Adjust the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT 4 /* Extract timestamp from packet */ +#define NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE 5 /* Prepare timestamp for packet */ +#define NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE 6 /* Update timer for soft implementation */ + + +/* Master messages data */ +typedef struct NX_PTP_CLIENT_MASTER_STRUCT +{ + NXD_ADDRESS *nx_ptp_client_master_address; + UCHAR *nx_ptp_client_master_port_identity; + UCHAR nx_ptp_client_master_priority1; + UCHAR nx_ptp_client_master_priority2; + UCHAR nx_ptp_client_master_clock_class; + UCHAR nx_ptp_client_master_clock_accuracy; + USHORT nx_ptp_client_master_offset_scaled_log_variance; + UCHAR *nx_ptp_client_master_grandmaster_identity; + USHORT nx_ptp_client_master_steps_removed; + UCHAR nx_ptp_client_master_time_source; +} NX_PTP_CLIENT_MASTER; + +/* Sync flags */ +#define NX_PTP_CLIENT_SYNC_CALIBRATED (1 << 0) +#define NX_PTP_CLIENT_SYNC_UTC_REASONABLE (1 << 1) +#define NX_PTP_CLIENT_SYNC_LEAP59 (1 << 2) +#define NX_PTP_CLIENT_SYNC_LEAP61 (1 << 3) + +/* Sync message data */ +typedef struct NX_PTP_CLIENT_SYNC_STRUCT +{ + USHORT nx_ptp_client_sync_flags; + SHORT nx_ptp_client_sync_utc_offset; +} NX_PTP_CLIENT_SYNC; + + +/* Define the Type of messages */ + +#define NX_PTP_CLIENT_ALL_EVENTS 0xFFFFFFFF /* all events of PTP client */ +#define NX_PTP_CLIENT_STOP_EVENT 0x00000001 /* stop the PTP client */ +#define NX_PTP_CLIENT_RX_EVENT 0x00000002 /* received UDP packet */ +#define NX_PTP_CLIENT_TIMER_EVENT 0x00000004 /* timer tick */ + + +/* Define the size of the PTP client message queue */ + +#define NX_PTP_CLIENT_MESSAGE_QUEUE_SIZE 16 + + +/* Define the state of the PTP Client thread */ + +#define NX_PTP_CLIENT_THREAD_IDLE 0 +#define NX_PTP_CLIENT_THREAD_RUNNING 1 +#define NX_PTP_CLIENT_THREAD_STOPPING 2 +#define NX_PTP_CLIENT_THREAD_STOPPED 3 + + +/* Define the state of the PTP Client clock */ + +#define NX_PTP_CLIENT_STATE_LISTENING 0 +#define NX_PTP_CLIENT_STATE_WAIT_SYNC 1 +#define NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP 2 + + +/* Define the state of the delay measurement process */ + +#define NX_PTP_CLIENT_DELAY_IDLE 0 +#define NX_PTP_CLIENT_DELAY_WAIT_REQ_TS 1 +#define NX_PTP_CLIENT_DELAY_WAIT_RESP 2 + + +/* Define the structure of a PTP Client */ + +typedef struct NX_PTP_CLIENT_STRUCT +{ + /* PTP Client ID */ + ULONG nx_ptp_client_id; + + /* Pointer to the Client IP instance. */ + NX_IP *nx_ptp_client_ip_ptr; + + /* Index to PTP network interface */ + UINT nx_ptp_client_interface_index; + + /* Pointer to the Client packet pool. */ + NX_PACKET_POOL *nx_ptp_client_packet_pool_ptr; + + /* PTP Domain Number */ + UCHAR nx_ptp_client_domain; + + /* PTP Transport Specific */ + UCHAR nx_ptp_client_transport_specific; + + /* PTP Client Port and Identity */ + UCHAR nx_ptp_client_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE]; + + /* PTP event handler callback */ + NX_PTP_CLIENT_EVENT_CALLBACK nx_ptp_client_event_callback; + VOID *nx_ptp_client_event_callback_data; + + /* PTP clock callback */ + NX_PTP_CLIENT_CLOCK_CALLBACK nx_ptp_client_clock_callback; + VOID *nx_ptp_client_clock_callback_data; + + /* PTP General Messages UDP Socket */ + NX_UDP_SOCKET nx_ptp_client_general_socket; + + /* PTP Event Messages UDP Socket */ + NX_UDP_SOCKET nx_ptp_client_event_socket; + + /* The message queue */ + TX_EVENT_FLAGS_GROUP nx_ptp_client_events; + + /* Set if IPv4 multicast group has been joined */ + UCHAR nx_ptp_client_ipv4_group_joined; + +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + /* Set if IPv6 multicast group has been joined */ + UCHAR nx_ptp_client_ipv6_group_joined; +#endif + + /* The software clock value */ + NX_PTP_TIME nx_ptp_client_soft_clock; + + /* The state of the PTP client */ + UCHAR nx_ptp_client_state; + + /* The state of the delay measurement */ + UCHAR nx_ptp_client_delay_state; + + /* The current UTC offset flags */ + USHORT nx_ptp_client_sync_flags; + + /* The current UTC offset */ + SHORT nx_ptp_client_utc_offset; + + /* The address of the master clock */ + NXD_ADDRESS nx_ptp_client_master_addr; + + /* The identity of the master clock */ + UCHAR nx_ptp_client_master_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE]; + + /* The current sync master timestamp */ + NX_PTP_TIME nx_ptp_client_sync; + + /* The current sync client timestamp */ + NX_PTP_TIME nx_ptp_client_sync_ts; + + /* The id of the sync message */ + USHORT nx_ptp_client_sync_id; + + /* The id of the last delay_req message */ + USHORT nx_ptp_client_delay_req_id; + + /* The delay request interval timer */ + INT nx_ptp_client_delay_req_timer; + + /* The Announce timeout */ + INT nx_ptp_client_announce_timeout; + + /* The delay request flag */ + UINT nx_ptp_client_delay_req_flag; + + /* The delay request client timestamp */ + NX_PTP_TIME nx_ptp_client_delay_ts; + + /* The delay request packet pointer */ + NX_PACKET *nx_ptp_client_delay_req_packet_ptr; + + /* The PTP client timer */ + TX_TIMER nx_ptp_client_timer; + + /* The current state of the PTP Client thread */ + UINT nx_ptp_client_thread_state; + + /* The PTP client processing thread */ + TX_THREAD nx_ptp_client_thread; +} NX_PTP_CLIENT; + + +#ifndef NX_PTP_SOURCE_CODE + +/* Define the system API mappings based on the error checking selected by the user. */ + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + + +#ifdef NX_PTP_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define nx_ptp_client_create _nx_ptp_client_create +#define nx_ptp_client_delete _nx_ptp_client_delete +#define nx_ptp_client_start _nx_ptp_client_start +#define nx_ptp_client_stop _nx_ptp_client_stop +#define nx_ptp_client_time_get _nx_ptp_client_time_get +#define nx_ptp_client_time_set _nx_ptp_client_time_set +#define nx_ptp_client_master_info_get _nx_ptp_client_master_info_get +#define nx_ptp_client_sync_info_get _nx_ptp_client_sync_info_get +#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify +#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback +#define nx_ptp_client_utility_time_diff _nx_ptp_client_utility_time_diff +#define nx_ptp_client_utility_convert_time_to_date _nx_ptp_client_utility_convert_time_to_date + +#else + +/* Services with error checking. */ + +#define nx_ptp_client_create _nxe_ptp_client_create +#define nx_ptp_client_delete _nxe_ptp_client_delete +#define nx_ptp_client_start _nxe_ptp_client_start +#define nx_ptp_client_stop _nxe_ptp_client_stop +#define nx_ptp_client_time_get _nxe_ptp_client_time_get +#define nx_ptp_client_time_set _nxe_ptp_client_time_set +#define nx_ptp_client_master_info_get _nxe_ptp_client_master_info_get +#define nx_ptp_client_sync_info_get _nxe_ptp_client_sync_info_get +#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify +#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback +#define nx_ptp_client_utility_time_diff _nxe_ptp_client_utility_time_diff +#define nx_ptp_client_utility_convert_time_to_date _nxe_ptp_client_utility_convert_time_to_date + +#endif + +#endif + + +/* Define the function prototypes of the PTP Client API */ + +UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data); +UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr); +UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data); +UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr); +UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source); +UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset); +UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr); +UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr); +VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr); +UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data); + +UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data); +UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr); +UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data); +UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr); +UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source); +UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset); +UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr); +UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr); + + +/* Define the function prototypes of the private utility functions */ + +VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr); +VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo); +VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo); +VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo); +VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo); +VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo); + + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus +} +#endif + +#endif /* NX_PTP_CLIENT_H */ diff --git a/common/inc/nx_api.h b/common/inc/nx_api.h index cd56b4eb..a48e15b4 100644 --- a/common/inc/nx_api.h +++ b/common/inc/nx_api.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_api.h PORTABLE C */ -/* 6.1.2 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -52,6 +52,12 @@ /* 11-09-2020 Yuxin Zhou Modified comment(s), and */ /* updated product constants, */ /* resulting in version 6.1.2 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), added */ +/* PTP timestamp capability, */ +/* added function to convert */ +/* string to unsigned integer, */ +/* updated product constants, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -459,7 +465,7 @@ VOID _nx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG #define AZURE_RTOS_NETXDUO #define NETXDUO_MAJOR_VERSION 6 #define NETXDUO_MINOR_VERSION 1 -#define NETXDUO_PATCH_VERSION 2 +#define NETXDUO_PATCH_VERSION 3 /* Define the following symbols for backward compatibility */ #define EL_PRODUCT_NETXDUO @@ -1301,6 +1307,7 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM 0x00000200 #define NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM 0x00000400 #define NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM 0x00000800 +#define NX_INTERFACE_CAPABILITY_PTP_TIMESTAMP 0x00001000 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ #define NX_IP_VERSION_V4 0x4 @@ -3803,6 +3810,7 @@ VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index); /* Utility functions. */ UINT _nx_utility_string_length_check(CHAR *input_string, UINT *string_length, UINT max_string_length); +UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number); /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/src/nx_ipv6_process_hop_by_hop_option.c b/common/src/nx_ipv6_process_hop_by_hop_option.c index cef14f7b..c5881662 100644 --- a/common/src/nx_ipv6_process_hop_by_hop_option.c +++ b/common/src/nx_ipv6_process_hop_by_hop_option.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_process_hop_by_hop_option PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer read overflow check, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ipv6_process_hop_by_hop_option(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -87,6 +90,14 @@ NX_IPV6_HOP_BY_HOP_OPTION *option; /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); + /* Make sure there's no OOB when reading Hdr Ext Len from the packet buffer. */ + if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < 2) + { + + /* return an error code. */ + return(NX_OPTION_HEADER_ERROR); + } + /* Read the Hdr Ext Len field. */ header_length = *(packet_ptr -> nx_packet_prepend_ptr + 1); diff --git a/common/src/nx_utility.c b/common/src/nx_utility.c index eb2aac31..60e750b7 100644 --- a/common/src/nx_utility.c +++ b/common/src/nx_utility.c @@ -107,3 +107,93 @@ UINT i; return(NX_SUCCESS); } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_utility_string_to_uint PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts the string to unsigned integer. */ +/* */ +/* INPUT */ +/* */ +/* input_string Pointer to input string */ +/* string_length Length of input string */ +/* number Pointer to the number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number) +{ + +UINT i; + + + /* Check for invalid input pointers. */ + if ((input_string == NX_NULL) || (number == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Check string length. */ + if (string_length == 0) + { + return(NX_SIZE_ERROR); + } + + /* Initialize. */ + i = 0; + *number = 0; + + /* Traverse the string. */ + while (i < string_length) + { + + /* Is a numeric character present? */ + if ((input_string[i] >= '0') && (input_string[i] <= '9')) + { + + /* Check overflow. Max Value: Hex:0xFFFFFFFF, Decimal: 4294967295. */ + if (((*number == 429496729) && (input_string[i] > '5')) || + (*number >= 429496730)) + { + return(NX_OVERFLOW); + } + + /* Yes, numeric character is present. Update the number. */ + *number = (*number * 10) + (UINT) (input_string[i] - '0'); + } + else + { + return(NX_INVALID_PARAMETERS); + } + + i++; + } + + /* Return success. */ + return(NX_SUCCESS); +} diff --git a/nx_secure/inc/nx_secure_dtls.h b/nx_secure/inc/nx_secure_dtls.h index c1de4f47..f2fb6d75 100644 --- a/nx_secure/inc/nx_secure_dtls.h +++ b/nx_secure/inc/nx_secure_dtls.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_secure_dtls.h PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -43,6 +43,10 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -437,7 +441,7 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length, + UINT *header_size, UINT *message_length, UINT *message_seq, UINT *fragment_offset, UINT *fragment_length); @@ -463,7 +467,7 @@ UINT _nx_secure_dtls_send_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET UCHAR record_type, ULONG wait_option); UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, - ULONG wait_option); + UINT data_length, ULONG wait_option); UINT _nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet); diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h index 7eb5892d..ef3f8975 100644 --- a/nx_secure/inc/nx_secure_tls.h +++ b/nx_secure/inc/nx_secure_tls.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_secure_tls.h PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -52,6 +52,11 @@ /* bug, fixed certificate */ /* buffer allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* updated product constants, */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -112,7 +117,7 @@ extern "C" { #define AZURE_RTOS_NETX_SECURE #define NETX_SECURE_MAJOR_VERSION 6 #define NETX_SECURE_MINOR_VERSION 1 -#define NETX_SECURE_PATCH_VERSION 0 +#define NETX_SECURE_PATCH_VERSION 3 /* The following symbols are defined for backward compatibility reasons. */ #define EL_PRODUCT_NETX_SECURE @@ -1390,7 +1395,7 @@ UINT _nx_secure_tls_process_header(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET ULONG record_offset, USHORT *message_type, UINT *length, UCHAR *header_data, USHORT *header_length); UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length); + UINT *header_size, UINT *message_length); UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr, ULONG *bytes_processed, ULONG wait_option); UINT _nx_secure_tls_process_remote_certificate(NX_SECURE_TLS_SESSION *tls_session, diff --git a/nx_secure/src/nx_secure_dtls_client_handshake.c b/nx_secure/src/nx_secure_dtls_client_handshake.c index a6ad765e..57b71772 100644 --- a/nx_secure/src/nx_secure_dtls_client_handshake.c +++ b/nx_secure/src/nx_secure_dtls_client_handshake.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -110,6 +110,11 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, added null */ +/* pointer checking, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, @@ -118,7 +123,7 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA #ifndef NX_SECURE_TLS_CLIENT_DISABLED UINT status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UCHAR *data_start = NX_NULL; NX_PACKET *send_packet = NX_NULL; @@ -146,6 +151,7 @@ NX_SECURE_TLS_SESSION *tls_session; while (data_length > 0) { + header_bytes = data_length; /* First, process the handshake message to get our state and any data therein. */ status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes, @@ -169,6 +175,12 @@ NX_SECURE_TLS_SESSION *tls_session; return(NX_SUCCESS); } + /* Check the fragment_length with the lenght of packet buffer. */ + if ((header_bytes + fragment_length) > data_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Check available area of buffer. */ if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size || (header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size) @@ -381,7 +393,7 @@ NX_SECURE_TLS_SESSION *tls_session; /* Get ClientHello packet from header of transmit queue. */ send_packet = dtls_session -> nx_secure_dtls_transmit_sent_head; - if (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE)) + if ((send_packet == NX_NULL) || (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE))) { /* Invalid packet. */ @@ -592,8 +604,8 @@ NX_SECURE_TLS_SESSION *tls_session; return(error_number); } - /* Advance the buffer pointer past the message. */ - packet_buffer += (message_length + header_bytes); + /* Advance the buffer pointer past the fragment. */ + packet_buffer += (fragment_length + header_bytes); } /* End while. */ return(NX_SUCCESS); #else /* TLS Client disabled. */ diff --git a/nx_secure/src/nx_secure_dtls_process_clienthello.c b/nx_secure/src/nx_secure_dtls_process_clienthello.c index dae013b1..08fb37be 100644 --- a/nx_secure/src/nx_secure_dtls_process_clienthello.c +++ b/nx_secure/src/nx_secure_dtls_process_clienthello.c @@ -40,7 +40,7 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_clienthello PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -90,6 +90,10 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN /* renegotiation bug, */ /* improved negotiation logic, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, @@ -243,6 +247,12 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; compression_methods_length = packet_buffer[0]; packet_buffer += 1; + /* Message length overflow. */ + if (((UINT)(packet_buffer - packet_buffer_start + compression_methods_length)) > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Make sure NULL compression method is supported. */ status = NX_SECURE_TLS_BAD_COMPRESSION_METHOD; for (i = 0; i < compression_methods_length; ++i) diff --git a/nx_secure/src/nx_secure_dtls_process_handshake_header.c b/nx_secure/src/nx_secure_dtls_process_handshake_header.c index ec08cc95..69fe356d 100644 --- a/nx_secure/src/nx_secure_dtls_process_handshake_header.c +++ b/nx_secure/src/nx_secure_dtls_process_handshake_header.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_handshake_header PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -45,7 +45,8 @@ /* */ /* packet_buffer Pointer to incoming packet */ /* message_type Return message type value */ -/* header_size Return size of header */ +/* header_size Input size of packet buffer */ +/* Return size of header */ /* message_length Return length of message */ /* message_seq Return sequence of message */ /* fragment_offset Return offset of fragment */ @@ -71,13 +72,24 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length, + UINT *header_size, UINT *message_length, UINT *message_seq, UINT *fragment_offset, UINT *fragment_length) { + + /* Check buffer length. */ + if (*header_size < NX_SECURE_DTLS_HANDSHAKE_HEADER_SIZE) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* The message being passed in to this function should already be stripped of the TLS header so the first byte in the packet/record is our handshake message type. */ *message_type = packet_buffer[0]; diff --git a/nx_secure/src/nx_secure_dtls_process_record.c b/nx_secure/src/nx_secure_dtls_process_record.c index 906eb1e1..d5ef73b1 100644 --- a/nx_secure/src/nx_secure_dtls_process_record.c +++ b/nx_secure/src/nx_secure_dtls_process_record.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_record PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -80,6 +80,10 @@ /* adjusted logic for TLS */ /* modifications, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr, @@ -246,7 +250,7 @@ NX_PACKET *decrypted_packet; /* The socket is a TLS server, so process incoming handshake messages in that context. */ if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) { - status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, wait_option); + status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, message_length, wait_option); } #endif #ifndef NX_SECURE_TLS_CLIENT_DISABLED diff --git a/nx_secure/src/nx_secure_dtls_server_handshake.c b/nx_secure/src/nx_secure_dtls_server_handshake.c index b437bf33..640edd7a 100644 --- a/nx_secure/src/nx_secure_dtls_server_handshake.c +++ b/nx_secure/src/nx_secure_dtls_server_handshake.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_server_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -48,6 +48,7 @@ /* */ /* dtls_session TLS control block */ /* packet_buffer Pointer into record buffer */ +/* data_length Length of data */ /* wait_option Controls timeout actions */ /* */ /* OUTPUT */ @@ -110,15 +111,19 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, - ULONG wait_option) + UINT data_length, ULONG wait_option) { #ifndef NX_SECURE_TLS_SERVER_DISABLED UINT status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT message_seq; UINT fragment_offset; @@ -150,6 +155,8 @@ UCHAR *fragment_buffer; /* Use the TLS packet buffer for fragment processing. */ fragment_buffer = tls_session->nx_secure_tls_packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length, &message_seq, &fragment_offset, &fragment_length); @@ -178,6 +185,12 @@ UCHAR *fragment_buffer; return(1); } + /* Check the fragment_length with the lenght of packet buffer. */ + if ((header_bytes + fragment_length) > data_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Check available area of buffer. */ if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size || (header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size) diff --git a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c index fcb16303..4c352911 100644 --- a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c +++ b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -108,6 +108,10 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ @@ -141,7 +145,7 @@ UINT _nx_secure_tls_1_3_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH #ifndef NX_SECURE_TLS_CLIENT_DISABLED UINT status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT packet_buffer_length = data_length; UCHAR *packet_start; @@ -215,8 +219,15 @@ const UCHAR *server_random; * so we can hash it. */ packet_start = packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } /* Check for fragmented records. */ if((message_length + header_bytes) > data_length) diff --git a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c index 20eacdfe..4e78db77 100644 --- a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c +++ b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_server_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -99,6 +99,10 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -108,7 +112,7 @@ UINT _nx_secure_tls_1_3_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH #ifndef NX_SECURE_TLS_SERVER_DISABLED UINT status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; NX_PACKET *send_packet; NX_PACKET_POOL *packet_pool; @@ -175,7 +179,14 @@ NX_SECURE_TLS_SERVER_STATE old_server_state; /* Save a pointer to the start of our packet for the hash that happens below. */ packet_start = packet_buffer; - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + header_bytes = data_length; + + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } /* Check for fragmented records. */ if((message_length + header_bytes) > data_length) diff --git a/nx_secure/src/nx_secure_tls_client_handshake.c b/nx_secure/src/nx_secure_tls_client_handshake.c index fb269fd1..f7792505 100644 --- a/nx_secure/src/nx_secure_tls_client_handshake.c +++ b/nx_secure/src/nx_secure_tls_client_handshake.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -107,6 +107,10 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -116,7 +120,7 @@ UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR * UINT status; UINT temp_status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT packet_buffer_length = data_length; UCHAR *packet_start; @@ -142,8 +146,15 @@ const NX_CRYPTO_METHOD * so we can hash it. */ packet_start = packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } /* Check for fragmented records. */ if((message_length + header_bytes) > data_length) diff --git a/nx_secure/src/nx_secure_tls_process_handshake_header.c b/nx_secure/src/nx_secure_tls_process_handshake_header.c index b28a398e..226362eb 100644 --- a/nx_secure/src/nx_secure_tls_process_handshake_header.c +++ b/nx_secure/src/nx_secure_tls_process_handshake_header.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_handshake_header PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -46,7 +46,8 @@ /* */ /* packet_buffer Pointer to incoming packet */ /* message_type Return message type value */ -/* header_size Return size of header */ +/* header_size Input size of packet buffer */ +/* Return size of header */ /* message_length Return length of message */ /* */ /* OUTPUT */ @@ -69,12 +70,22 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length) + UINT *header_size, UINT *message_length) { + /* Check buffer length. */ + if (*header_size < 4) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* The message being passed in to this function should already be stripped of the TLS header so the first byte in the packet/record is our handshake message type. */ *message_type = packet_buffer[0]; diff --git a/nx_secure/src/nx_secure_tls_server_handshake.c b/nx_secure/src/nx_secure_tls_server_handshake.c index 729410e2..6eb265c7 100644 --- a/nx_secure/src/nx_secure_tls_server_handshake.c +++ b/nx_secure/src/nx_secure_tls_server_handshake.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_server_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -99,6 +99,10 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -108,7 +112,7 @@ UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR * UINT status; UINT temp_status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; NX_PACKET *send_packet; NX_PACKET_POOL *packet_pool; @@ -127,7 +131,14 @@ const NX_CRYPTO_METHOD *method_ptr = NX_NULL; /* Save a pointer to the start of our packet for the hash that happens below. */ packet_start = packet_buffer; - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + header_bytes = data_length; + + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } /* Check for fragmented records. */ if((message_length + header_bytes) > data_length) diff --git a/ports/cortex_m23/ac5/inc/nx_port.h b/ports/cortex_m23/ac5/inc/nx_port.h new file mode 100644 index 00000000..34bb804d --- /dev/null +++ b/ports/cortex_m23/ac5/inc/nx_port.h @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/AC5 */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG i; \ + ULONG tmp; \ + i = (UINT)arg; \ + /* i = A, B, C, D */ \ + tmp = i ^ (((i) >> 16) | (i << 16)); \ + /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + tmp &= 0xff00ffff; \ + /* tmp = A^C, 0, C^A, D^B */ \ + i = ((i) >> 8) | (i<<24); \ + /* i = D, A, B, C */ \ + i = i ^ ((tmp) >> 8); \ + /* i = D, C, B, A */ \ + arg = i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/AC5 Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m23/gnu/inc/nx_port.h b/ports/cortex_m23/gnu/inc/nx_port.h new file mode 100644 index 00000000..f7b75879 --- /dev/null +++ b/ports/cortex_m23/gnu/inc/nx_port.h @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/GNU */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +/* By default IPv6 is enabled. */ + +#ifndef FEATURE_NX_IPV6 +#define FEATURE_NX_IPV6 +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_DISABLE_IPV6 +#undef FEATURE_NX_IPV6 +#endif /* !NX_DISABLE_IPV6 */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/GNU Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m23/iar/inc/nx_port.h b/ports/cortex_m23/iar/inc/nx_port.h new file mode 100644 index 00000000..cc714693 --- /dev/null +++ b/ports/cortex_m23/iar/inc/nx_port.h @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/IAR */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/IAR Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m33/ac5/inc/nx_port.h b/ports/cortex_m33/ac5/inc/nx_port.h new file mode 100644 index 00000000..3ec61534 --- /dev/null +++ b/ports/cortex_m33/ac5/inc/nx_port.h @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/AC5 */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG i; \ + ULONG tmp; \ + i = (UINT)arg; \ + /* i = A, B, C, D */ \ + tmp = i ^ (((i) >> 16) | (i << 16)); \ + /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + tmp &= 0xff00ffff; \ + /* tmp = A^C, 0, C^A, D^B */ \ + i = ((i) >> 8) | (i<<24); \ + /* i = D, A, B, C */ \ + i = i ^ ((tmp) >> 8); \ + /* i = D, C, B, A */ \ + arg = i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC5 Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m33/gnu/inc/nx_port.h b/ports/cortex_m33/gnu/inc/nx_port.h new file mode 100644 index 00000000..bdf29114 --- /dev/null +++ b/ports/cortex_m33/gnu/inc/nx_port.h @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/GNU */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +/* By default IPv6 is enabled. */ + +#ifndef FEATURE_NX_IPV6 +#define FEATURE_NX_IPV6 +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_DISABLE_IPV6 +#undef FEATURE_NX_IPV6 +#endif /* !NX_DISABLE_IPV6 */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/GNU Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m33/iar/inc/nx_port.h b/ports/cortex_m33/iar/inc/nx_port.h new file mode 100644 index 00000000..598fcbee --- /dev/null +++ b/ports/cortex_m33/iar/inc/nx_port.h @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/IAR */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/IAR Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/rxv2/ccrx/inc/nx_port.h b/ports/rxv2/ccrx/inc/nx_port.h new file mode 100644 index 00000000..4f825f35 --- /dev/null +++ b/ports/rxv2/ccrx/inc/nx_port.h @@ -0,0 +1,221 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/CCRX */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +/* By default IPv6 is enabled. */ + +#ifndef FEATURE_NX_IPV6 +#define FEATURE_NX_IPV6 +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_DISABLE_IPV6 +#undef FEATURE_NX_IPV6 +#endif /* !NX_DISABLE_IPV6 */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG i; \ + ULONG tmp; \ + i = (UINT)arg; \ + /* i = A, B, C, D */ \ + tmp = i ^ (((i) >> 16) | (i << 16)); \ + /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + tmp &= 0xff00ffff; \ + /* tmp = A^C, 0, C^A, D^B */ \ + i = ((i) >> 8) | (i<<24); \ + /* i = D, A, B, C */ \ + i = i ^ ((tmp) >> 8); \ + /* i = D, C, B, A */ \ + arg = i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/CCRX Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/rxv2/gnu/inc/nx_port.h b/ports/rxv2/gnu/inc/nx_port.h new file mode 100644 index 00000000..e42bc47f --- /dev/null +++ b/ports/rxv2/gnu/inc/nx_port.h @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/GNU */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG i; \ + ULONG tmp; \ + i = (UINT)arg; \ + /* i = A, B, C, D */ \ + tmp = i ^ (((i) >> 16) | (i << 16)); \ + /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + tmp &= 0xff00ffff; \ + /* tmp = A^C, 0, C^A, D^B */ \ + i = ((i) >> 8) | (i<<24); \ + /* i = D, A, B, C */ \ + i = i ^ ((tmp) >> 8); \ + /* i = D, C, B, A */ \ + arg = i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/GNU Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/rxv2/iar/inc/nx_port.h b/ports/rxv2/iar/inc/nx_port.h new file mode 100644 index 00000000..6d2aa13f --- /dev/null +++ b/ports/rxv2/iar/inc/nx_port.h @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/IAR */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG i; \ + ULONG tmp; \ + i = (UINT)arg; \ + /* i = A, B, C, D */ \ + tmp = i ^ (((i) >> 16) | (i << 16)); \ + /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + tmp &= 0xff00ffff; \ + /* tmp = A^C, 0, C^A, D^B */ \ + i = ((i) >> 8) | (i<<24); \ + /* i = D, A, B, C */ \ + i = i ^ ((tmp) >> 8); \ + /* i = D, C, B, A */ \ + arg = i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/IAR Version 6.1.3 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/samples/demo_netx_duo_ptp_client.c b/samples/demo_netx_duo_ptp_client.c new file mode 100644 index 00000000..cb77b07d --- /dev/null +++ b/samples/demo_netx_duo_ptp_client.c @@ -0,0 +1,271 @@ +/* + This is a small demo of the NetX Duo PTP client on the high-performance NetX Duo TCP/IP stack. + This demo relies on ThreadX, NetX Duo and NetX Duo PTP client API to execute the Precision Time + Protocol. + + */ + +#include <stdio.h> +#include "nx_api.h" +#include "nxd_ptp_client.h" + +#ifndef SAMPLE_DHCP_DISABLE +#include "nxd_dhcp_client.h" +#endif /* SAMPLE_DHCP_DISABLE */ + +#define PTP_THREAD_PRIORITY 2 + +/* Define the ThreadX and NetX object control blocks... */ +static TX_THREAD thread_0; +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; +#ifndef SAMPLE_DHCP_DISABLE +static NX_DHCP dhcp_client; +#endif /* SAMPLE_DHCP_DISABLE */ +static NX_PTP_CLIENT ptp_client; + +/* Define the IP thread's stack area. */ +static ULONG ip_thread_stack[2048 / sizeof(ULONG)]; + +/* Define packet pool for the demonstration. */ +static ULONG packet_pool_area[((1536 + sizeof(NX_PACKET)) * 32) / sizeof(ULONG)]; + +/* Define the ARP cache area. */ +static ULONG arp_space_area[512 / sizeof(ULONG)]; + +/* Define the main thread. */ +static ULONG thread_0_stack[2048 / sizeof(ULONG)]; +static ULONG ptp_stack[2048 / sizeof(ULONG)]; + +/* Define an error counter. */ +static ULONG error_counter; + +/* Define ptp utc offset. */ +static SHORT ptp_utc_offset = 0; + +#ifndef SAMPLE_DHCP_DISABLE +#define IPV4_ADDRESS IP_ADDRESS(0, 0, 0, 0) +#define IPV4_NETWORK_MASK IP_ADDRESS(0, 0, 0, 0) +#else +#define IPV4_ADDRESS IP_ADDRESS(10, 1, 0, 212) +#define IPV4_NETWORK_MASK IP_ADDRESS(255, 255, 0, 0) +#define IPV4_GATEWAY_ADDR IP_ADDRESS(10, 1, 0, 1) +#define DNS_SERVER_ADDRESS IP_ADDRESS(10, 1, 0, 1) +#endif /* SAMPLE_DHCP_DISABLE */ + +/* Define the main thread entry point. */ +static VOID thread_0_entry(ULONG thread_input); + +/* PTP handler. */ +static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data); + +#ifndef SAMPLE_DHCP_DISABLE +static void dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + +/***** Substitute your ethernet driver entry function here *********/ +#ifndef NETWORK_DRIVER +#define NETWORK_DRIVER _nx_ram_network_driver +#endif +extern VOID NETWORK_DRIVER(NX_IP_DRIVER *driver_req_ptr); + +#ifndef CLOCK_CALLBACK +#define CLOCK_CALLBACK nx_ptp_client_soft_clock_callback +#endif +extern UINT CLOCK_CALLBACK(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data); + +#ifdef HARDWARE_SETUP +extern VOID HARDWARE_SETUP(); +#endif + +int main() +{ +#ifdef HARDWARE_SETUP + HARDWARE_SETUP(); +#endif + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); + return 0; +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +UINT status; + + + /* Initialize the NetX system. */ + nx_system_initialize(); + + /* Create a packet pool. */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, (ULONG*)(((int)packet_pool_area + 15) & ~15) , sizeof(packet_pool_area)); + + /* Check for pool creation error. */ + if (status) + error_counter++; + + /* Create an IP instance. */ + status = nx_ip_create(&ip_0, + "NetX IP Instance 0", + IPV4_ADDRESS, + IPV4_NETWORK_MASK, + &pool_0, + NETWORK_DRIVER, + (UCHAR*)ip_thread_stack, + sizeof(ip_thread_stack), + 1); + + /* Check for IP create errors. */ + if (status) + error_counter++; + + /* Enable ARP and supply ARP cache memory for IP Instance 0. */ + status = nx_arp_enable(&ip_0, (void *)arp_space_area, sizeof(arp_space_area)); + + /* Check for ARP enable errors. */ + if (status) + error_counter++; + + /* Enable TCP traffic. */ + status = nx_tcp_enable(&ip_0); + + /* Check for TCP enable errors. */ + if (status) + error_counter++; + + /* Enable UDP traffic. */ + status = nx_udp_enable(&ip_0); + + /* Check for UDP enable errors. */ + if (status) + error_counter++; + + /* Enable ICMP. */ + status = nx_icmp_enable(&ip_0); + + /* Check for errors. */ + if (status) + error_counter++; + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + thread_0_stack, sizeof(thread_0_stack), + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/* Define the test threads. */ +void thread_0_entry(ULONG thread_input) +{ + +NX_PTP_TIME tm; +NX_PTP_DATE_TIME date; + +#ifndef SAMPLE_DHCP_DISABLE + dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + + /* Create the PTP client instance */ + nx_ptp_client_create(&ptp_client, &ip_0, 0, &pool_0, + PTP_THREAD_PRIORITY, (UCHAR *)ptp_stack, sizeof(ptp_stack), + CLOCK_CALLBACK, NX_NULL); + + /* start the PTP client */ + nx_ptp_client_start(&ptp_client, NX_NULL, 0, 0, 0, ptp_event_callback, NX_NULL); + + while(1) + { + + /* read the PTP clock */ + nx_ptp_client_time_get(&ptp_client, &tm); + + /* convert PTP time to UTC date and time */ + nx_ptp_client_utility_convert_time_to_date(&tm, -ptp_utc_offset, &date); + + /* display the current time */ + printf("%2u/%02u/%u %02u:%02u:%02u.%09lu\r\n", date.day, date.month, date.year, date.hour, date.minute, date.second, date.nanosecond); + + tx_thread_sleep(NX_IP_PERIODIC_RATE); + } +} + +static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data) +{ + NX_PARAMETER_NOT_USED(callback_data); + + switch (event) + { + case NX_PTP_CLIENT_EVENT_MASTER: + { + printf("new MASTER clock!\r\n"); + break; + } + + case NX_PTP_CLIENT_EVENT_SYNC: + { + nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &ptp_utc_offset); + printf("SYNC event: utc offset=%d\r\n", ptp_utc_offset); + break; + } + + case NX_PTP_CLIENT_EVENT_TIMEOUT: + { + printf("Master clock TIMEOUT!\r\n"); + break; + } + default: + { + break; + } + } + + return 0; +} + +/* DHCP */ +#ifndef SAMPLE_DHCP_DISABLE +void dhcp_wait(void) +{ + +ULONG actual_status; +ULONG ip_address; +ULONG network_mask; +ULONG gw_address; + + printf("DHCP In Progress...\r\n"); + + /* Create the DHCP instance. */ + nx_dhcp_create(&dhcp_client, &ip_0, "dhcp_client"); + + /* Start the DHCP Client. */ + nx_dhcp_start(&dhcp_client); + + /* Wait util address is solved. */ + nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER); + + /* Get IP address. */ + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + nx_ip_gateway_address_get(&ip_0, &gw_address); + + /* Output IP address. */ + printf("IP address: %d.%d.%d.%d\r\nMask: %d.%d.%d.%d\r\nGateway: %d.%d.%d.%d\r\n", + (INT)(ip_address >> 24), + (INT)(ip_address >> 16 & 0xFF), + (INT)(ip_address >> 8 & 0xFF), + (INT)(ip_address & 0xFF), + (INT)(network_mask >> 24), + (INT)(network_mask >> 16 & 0xFF), + (INT)(network_mask >> 8 & 0xFF), + (INT)(network_mask & 0xFF), + (INT)(gw_address >> 24), + (INT)(gw_address >> 16 & 0xFF), + (INT)(gw_address >> 8 & 0xFF), + (INT)(gw_address & 0xFF)); +} +#endif /* SAMPLE_DHCP_DISABLE */
\ No newline at end of file |
