1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** NetX PTP Client Component                                             */
15 /**                                                                       */
16 /**   Precision Time Protocol (PTP)                                       */
17 /**                                                                       */
18 /**************************************************************************/
19 /**************************************************************************/
20 
21 /**************************************************************************/
22 /*                                                                        */
23 /*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
24 /*                                                                        */
25 /*    nxd_ptp_client.c                                    PORTABLE C      */
26 /*                                                           6.4.0        */
27 /*  AUTHOR                                                                */
28 /*                                                                        */
29 /*    Yuxin Zhou, Microsoft Corporation                                   */
30 /*                                                                        */
31 /*  DESCRIPTION                                                           */
32 /*                                                                        */
33 /*    This file defines the NetX Precision Time Protocol (PTP)            */
34 /*    Client component, including all data types and external references. */
35 /*                                                                        */
36 /*  RELEASE HISTORY                                                       */
37 /*                                                                        */
38 /*    DATE              NAME                      DESCRIPTION             */
39 /*                                                                        */
40 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
41 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
42 /*                                            supported gPTP profile,     */
43 /*                                            supported master clock,     */
44 /*                                            resulting in version 6.4.0  */
45 /*                                                                        */
46 /**************************************************************************/
47 
48 
49 /* Force error checking to be disabled in this module */
50 
51 #ifndef NX_DISABLE_ERROR_CHECKING
52 #define NX_DISABLE_ERROR_CHECKING
53 #endif
54 
55 #define NX_PTP_SOURCE_CODE
56 
57 #include "nxd_ptp_client.h"
58 #if NX_PTP_CLIENT_TRANSPORT_UDP
59 #include "nx_udp.h"
60 #include "nx_ipv4.h"
61 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
62 #include "nx_ipv6.h"
63 #endif
64 #endif
65 #include "tx_timer.h"
66 
67 /* #define NX_PTP_DEBUG */
68 /* #define NX_PTP_DEBUG_OFFSET */
69 /* #define NX_PTP_DEBUG_DELAY */
70 /* #define NX_PTP_DEBUG_RATE_RATIO */
71 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET) || defined(NX_PTP_DEBUG_DELAY) || defined(NX_PTP_DEBUG_RATE_RATIO)
72 #include <stdio.h>
73 #endif
74 #ifdef NX_PTP_DEBUG
75 #ifndef NX_PTP_DEBUG_PRINTF
76 #define NX_PTP_DEBUG_PRINTF(x) printf x
77 #endif
78 #else
79 #define NX_PTP_DEBUG_PRINTF(x)
80 #endif
81 
82 /* Bring in externs for caller checking code.  */
83 
84 NX_CALLER_CHECKING_EXTERNS
85 
86 /* number of nanoseconds per second */
87 #define NX_PTP_NANOSECONDS_PER_SEC             1000000000L
88 
89 /* Define the PTP version */
90 #define NX_PTP_VERSION                         2
91 
92 /* Define the UDP ports */
93 #define NX_PTP_EVENT_UDP_PORT                  319
94 #define NX_PTP_GENERAL_UDP_PORT                320
95 
96 /* Define the TTL of PTP packets */
97 #define NX_PTP_TIME_TO_LIVE                    1
98 
99 /* Define the IPv4 multicast address "224.0.1.129" */
100 #define NX_PTP_IPV4_MULTICAST_ADDR             IP_ADDRESS(224, 0, 1, 129)
101 
102 /* Define the IPv4 P2P multicast address "224.0.0.107" */
103 #define NX_PTP_IPV4_P2P_MULTICAST_ADDR         IP_ADDRESS(224, 0, 0, 107)
104 
105 /* Define the IPv6 multicast address "ff0e::181" */
106 #define NX_PTP_IPV6_MULTICAST_ADDR_SET(x)      {    \
107         (x) -> nxd_ip_version = NX_IP_VERSION_V6;   \
108         (x) -> nxd_ip_address.v6[0] = 0xff0e0000UL; \
109         (x) -> nxd_ip_address.v6[1] = 0;            \
110         (x) -> nxd_ip_address.v6[2] = 0;            \
111         (x) -> nxd_ip_address.v6[3] = 0x181; }
112 
113 /* Define the IPv6 multicast address "ff02::6b" */
114 #define NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(x)  {    \
115         (x) -> nxd_ip_version = NX_IP_VERSION_V6;   \
116         (x) -> nxd_ip_address.v6[0] = 0xff020000UL; \
117         (x) -> nxd_ip_address.v6[1] = 0;            \
118         (x) -> nxd_ip_address.v6[2] = 0;            \
119         (x) -> nxd_ip_address.v6[3] = 0x6b; }
120 
121 /* Define Ethernet type for PTPv2 over Ethernet */
122 #define NX_PTP_ETHERNET_TYPE                   0x88F7
123 
124 /* Define Ethernet multicast address for PTPv2 over Ethernet */
125 #define NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB 0x0180
126 #define NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB 0xC200000E
127 
128 /* Define Ethernet multicast address for all except peer delay messages */
129 #define NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_MSB 0x011b
130 #define NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_LSB 0x19000000
131 
132 
133 #if NX_PTP_CLIENT_TRANSPORT_UDP
134 #define NX_PTP_PACKET                          NX_UDP_PACKET
135 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
136 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
137 #define NX_PTP_PACKET                          NX_PHYSICAL_HEADER
138 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
139 
140 /* Length of PTP message header */
141 #define NX_PTP_MSG_HDR_LEN                     34
142 
143 /* Length of PTP messages (without header) */
144 #define NX_PTP_MSG_ANNOUNCE_LEN                30
145 #define NX_PTP_MSG_SYNC_LEN                    10
146 #define NX_PTP_MSG_FOLLOW_UP_LEN               10
147 #define NX_PTP_MSG_DELAY_RESP_LEN              20
148 
149 /* Length of PTP messages gPTP (without header) */
150 #define NX_PTP_MSG_PDELAY_REQ_LEN              20
151 #define NX_PTP_MSG_PDELAY_RESP_LEN             20
152 #define NX_PTP_MSG_PDELAY_RESP_FOLLOW_UP_LEN   20
153 #define NX_PTP_MSG_PDELAY_RESERVED_LEN         10
154 
155 /* Length of PTP timestamp */
156 #define NX_PTP_MSG_TIMESTAMP_LEN               10
157 
158 /* Length of PTP correctionField */
159 #define NX_PTP_MSG_CFIELD_TIMESTAMP_LEN        8
160 
161 /* Get version number */
162 #define NX_PTP_MSG_VERSION(p_)                 ((p_)[1] & 0xf)
163 
164 /* Get domain number */
165 #define NX_PTP_MSG_DOMAIN(p_)                  ((p_)[4])
166 
167 /* Type of messages */
168 #define NX_PTP_MSG_TYPE_SYNC                   0
169 #define NX_PTP_MSG_TYPE_DELAY_REQ              1
170 #define NX_PTP_MSG_TYPE_PDELAY_REQ             2
171 #define NX_PTP_MSG_TYPE_PDELAY_RESP            3
172 #define NX_PTP_MSG_TYPE_FOLLOW_UP              8
173 #define NX_PTP_MSG_TYPE_DELAY_RESP             9
174 #define NX_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP  10
175 #define NX_PTP_MSG_TYPE_ANNOUNCE               11
176 
177 /* Message flags */
178 #define NX_PTP_MSG_HDR_FLAG_LEAP61             (1 << 0)
179 #define NX_PTP_MSG_HDR_FLAG_LEAP59             (1 << 1)
180 #define NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE     (1 << 2)
181 #define NX_PTP_MSG_HDR_FLAG_TWO_STEP           (1 << 9)
182 
183 /* Common Message Header */
184 typedef struct NX_PTP_MSG_HEADER_STRUCT
185 {
186     UCHAR  transportSpecific;
187     UCHAR  messageType;
188     UCHAR  versionPTP;
189     UCHAR  domainNumber;
190     USHORT messageLength;
191     USHORT flagField;
192     ULONG  cFieldHigh;
193     ULONG  cFieldLow;
194     UCHAR *sourcePortIdentity;
195     USHORT sequenceId;
196     UCHAR  logMessageInterval;
197 } NX_PTP_MSG_HEADER;
198 
199 /* Get UTC offset from announce message */
200 #define NX_PTP_MSG_UTC_OFFSET(p_) ((SHORT)((p_[10] << 8) | p_[11]))
201 
202 /* Macros for reading PTP packet fields */
203 #define NX_PTP_RD16(p_, v_)       { \
204         USHORT t_;                  \
205         t_ = *p_++;                 \
206         t_ = (USHORT)(t_ << 8);     \
207         v_ = (USHORT)(t_ | *p_++); }
208 
209 #define NX_PTP_RD32(p_, v_)       { \
210         ULONG t_;                   \
211         t_ = *p_++;                 \
212         t_ <<= 8;                   \
213         t_ |= *p_++;                \
214         t_ <<= 8;                   \
215         t_ |= *p_++;                \
216         t_ <<= 8;                   \
217         v_ = t_ |= *p_++; }
218 
219 #if defined(NX_ENABLE_GPTP) || defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
_nx_ptp_utility_32_unsigned_write(UCHAR * dest_ptr,ULONG value)220 static VOID  _nx_ptp_utility_32_unsigned_write(UCHAR *dest_ptr, ULONG value)
221 {
222 
223     *(dest_ptr)     = (UCHAR)((value >> 24) & 0xFF);
224     *(dest_ptr + 1) = (UCHAR)((value >> 16) & 0xFF);
225     *(dest_ptr + 2) = (UCHAR)((value >> 8) & 0xFF);
226     *(dest_ptr + 3) = (UCHAR)(value & 0xFF);
227 }
228 #endif
229 
230 #define NX_PTP_TS_RESET(ts) (ts).second_high = 0; \
231                             (ts).second_low = 0;  \
232                             (ts).nanosecond = 0;  \
233 
234 #define NX_PTP_TS_COPY(ts1, ts2) (ts1).second_high = (ts2).second_high; \
235                                  (ts1).second_low = (ts2).second_low;   \
236                                  (ts1).nanosecond = (ts2).nanosecond;   \
237 
238 #define NX_PTP_TS_EQUAL(ts1, ts2) ((ts1).second_high == (ts2).second_high && \
239                                    (ts1).second_low == (ts2).second_low &&   \
240                                    (ts1).nanosecond == (ts2).nanosecond)
241 
242 /**************************************************************************/
243 /*                                                                        */
244 /*  FUNCTION                                               RELEASE        */
245 /*                                                                        */
246 /*    _nx_ptp_msg_parse_timestamp                         PORTABLE C      */
247 /*                                                           6.1.3        */
248 /*  AUTHOR                                                                */
249 /*                                                                        */
250 /*    Yuxin Zhou, Microsoft Corporation                                   */
251 /*                                                                        */
252 /*  DESCRIPTION                                                           */
253 /*                                                                        */
254 /*    This function parses timestamp field of a PTP message.              */
255 /*                                                                        */
256 /*  INPUT                                                                 */
257 /*                                                                        */
258 /*    ptr                                   Pointer to PTP message        */
259 /*    time_ptr                              Pointer to PTP time for output*/
260 /*                                                                        */
261 /*  OUTPUT                                                                */
262 /*                                                                        */
263 /*    None                                                                */
264 /*                                                                        */
265 /*  CALLS                                                                 */
266 /*                                                                        */
267 /*    None                                                                */
268 /*                                                                        */
269 /*  CALLED BY                                                             */
270 /*                                                                        */
271 /*    _nx_ptp_client_sync_received          Process Sync message          */
272 /*    _nx_ptp_client_delay_resp_received    Process delay response        */
273 /*                                                                        */
274 /*  RELEASE HISTORY                                                       */
275 /*                                                                        */
276 /*    DATE              NAME                      DESCRIPTION             */
277 /*                                                                        */
278 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
279 /*                                                                        */
280 /**************************************************************************/
_nx_ptp_msg_parse_timestamp(UCHAR * ptr,NX_PTP_TIME * time_ptr)281 static VOID _nx_ptp_msg_parse_timestamp(UCHAR *ptr, NX_PTP_TIME *time_ptr)
282 {
283 ULONG nanoseconds = (ULONG)time_ptr -> nanosecond;
284 
285     NX_PTP_RD16(ptr, time_ptr -> second_high);
286     NX_PTP_RD32(ptr, time_ptr -> second_low);
287     NX_PTP_RD32(ptr, nanoseconds);
288     time_ptr -> nanosecond = (LONG)nanoseconds;
289 }
290 
291 
292 /**************************************************************************/
293 /*                                                                        */
294 /*  FUNCTION                                               RELEASE        */
295 /*                                                                        */
296 /*    _nx_ptp_msg_parse_hdr                               PORTABLE C      */
297 /*                                                           6.4.0        */
298 /*  AUTHOR                                                                */
299 /*                                                                        */
300 /*    Yuxin Zhou, Microsoft Corporation                                   */
301 /*                                                                        */
302 /*  DESCRIPTION                                                           */
303 /*                                                                        */
304 /*    This function parses the header of a PTP packet.                    */
305 /*                                                                        */
306 /*  INPUT                                                                 */
307 /*                                                                        */
308 /*    client_ptr                            Pointer to PTP client         */
309 /*    packet_ptr                            Pointer to PTP packet         */
310 /*    hdr                                   Parsed PTP header for output  */
311 /*                                                                        */
312 /*  OUTPUT                                                                */
313 /*                                                                        */
314 /*    status                                Completion status             */
315 /*                                                                        */
316 /*  CALLS                                                                 */
317 /*                                                                        */
318 /*    nxd_udp_packet_info_extract           Extract UDP packet information*/
319 /*                                                                        */
320 /*  CALLED BY                                                             */
321 /*                                                                        */
322 /*    _nx_ptp_client_process_event_packet   Process PTP event packet      */
323 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
324 /*                                                                        */
325 /*  RELEASE HISTORY                                                       */
326 /*                                                                        */
327 /*    DATE              NAME                      DESCRIPTION             */
328 /*                                                                        */
329 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
330 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
331 /*                                            supported gPTP profile,     */
332 /*                                            resulting in version 6.4.0  */
333 /*                                                                        */
334 /**************************************************************************/
_nx_ptp_msg_parse_hdr(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_PTP_MSG_HEADER * hdr)335 static UINT _nx_ptp_msg_parse_hdr(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_MSG_HEADER *hdr)
336 {
337 UCHAR  b;
338 UCHAR *ptr;
339 UINT   len;
340 #if NX_PTP_CLIENT_TRANSPORT_UDP
341 UINT   status;
342 NXD_ADDRESS src_addr;
343 UINT   interface_index;
344 #endif
345 
346 #ifndef NX_DISABLE_PACKET_CHAIN
347     if (packet_ptr -> nx_packet_next)
348     {
349 
350         /* Chained packet is not supported */
351         return(NX_NOT_SUPPORTED);
352     }
353 #endif /* NX_DISABLE_PACKET_CHAIN */
354 
355     /* get pointer to PTP message */
356     ptr = packet_ptr -> nx_packet_prepend_ptr;
357 
358     /* get length of PTP message */
359     len = packet_ptr -> nx_packet_length;
360 
361     /* check packet validity: */
362     /* - length >= PTP header length */
363     /* - PTP version */
364     /* - domain number */
365     if ((len < NX_PTP_MSG_HDR_LEN) ||
366         (NX_PTP_MSG_VERSION(ptr) != NX_PTP_VERSION) ||
367         (NX_PTP_MSG_DOMAIN(ptr) != client_ptr -> nx_ptp_client_domain))
368     {
369 
370         /* discard invalid packet */
371         return(NX_INVALID_PACKET);
372     }
373 
374 #if NX_PTP_CLIENT_TRANSPORT_UDP
375     /* get info about sender and check packet validity: */
376     /* - network interface */
377     /* - IP version */
378     status = nxd_udp_packet_info_extract(packet_ptr, &src_addr, NX_NULL, NX_NULL, &interface_index);
379     if ((status != NX_SUCCESS) ||
380         (interface_index != client_ptr -> nx_ptp_client_interface_index)
381 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
382         || ((src_addr.nxd_ip_version == NX_IP_VERSION_V4) &&
383             !client_ptr -> nx_ptp_client_ipv4_group_joined) ||
384         ((src_addr.nxd_ip_version == NX_IP_VERSION_V6) &&
385             !client_ptr -> nx_ptp_client_ipv6_group_joined)
386 #endif
387         )
388     {
389 
390         /* discard invalid packet */
391         return(NX_INVALID_PACKET);
392     }
393 
394     /* Save source address in listening state */
395     if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
396     {
397         client_ptr -> nx_ptp_client_master_addr = src_addr;
398     }
399 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
400 
401     b = *ptr++;
402     hdr -> transportSpecific = b >> 4;
403     hdr -> messageType = b & 0xf;
404     b = *ptr++;
405     hdr -> versionPTP = b & 0xf;
406     NX_PTP_RD16(ptr, hdr -> messageLength);
407     hdr -> domainNumber = *ptr++;
408     ptr++;      /* reserved */
409     NX_PTP_RD16(ptr, hdr -> flagField);
410     NX_PTP_RD32(ptr, hdr -> cFieldHigh);
411     NX_PTP_RD32(ptr, hdr -> cFieldLow);
412     ptr += 4;   /* reserved */
413     hdr -> sourcePortIdentity = ptr;
414     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
415     NX_PTP_RD16(ptr, hdr -> sequenceId);
416     ptr++;      /* controlField - ignore */
417     hdr -> logMessageInterval = *ptr;
418 
419     /* adjust message length */
420     if (len > hdr -> messageLength)
421     {
422         if (hdr -> messageLength < NX_PTP_MSG_HDR_LEN)
423         {
424 
425             /* invalid length */
426             return(NX_INVALID_PACKET);
427         }
428         len = hdr -> messageLength;
429     }
430 
431     /* Adjust packet. */
432     packet_ptr -> nx_packet_prepend_ptr += NX_PTP_MSG_HDR_LEN;
433     packet_ptr -> nx_packet_length = len - NX_PTP_MSG_HDR_LEN;
434 
435     return(NX_SUCCESS);
436 }
437 
438 
439 /**************************************************************************/
440 /*                                                                        */
441 /*  FUNCTION                                               RELEASE        */
442 /*                                                                        */
443 /*    _nx_ptp_msg_parse_announce                          PORTABLE C      */
444 /*                                                           6.1.3        */
445 /*  AUTHOR                                                                */
446 /*                                                                        */
447 /*    Yuxin Zhou, Microsoft Corporation                                   */
448 /*                                                                        */
449 /*  DESCRIPTION                                                           */
450 /*                                                                        */
451 /*    This function parses PTP Announce message.                          */
452 /*                                                                        */
453 /*  INPUT                                                                 */
454 /*                                                                        */
455 /*    ptr                                   Pointer to PTP message        */
456 /*    master_ptr                            Parsed PTP master for output  */
457 /*                                                                        */
458 /*  OUTPUT                                                                */
459 /*                                                                        */
460 /*    None                                                                */
461 /*                                                                        */
462 /*  CALLS                                                                 */
463 /*                                                                        */
464 /*    None                                                                */
465 /*                                                                        */
466 /*  CALLED BY                                                             */
467 /*                                                                        */
468 /*    _nx_ptp_client_init_packet_received   Process Announce message      */
469 /*                                                                        */
470 /*  RELEASE HISTORY                                                       */
471 /*                                                                        */
472 /*    DATE              NAME                      DESCRIPTION             */
473 /*                                                                        */
474 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
475 /*                                                                        */
476 /**************************************************************************/
_nx_ptp_msg_parse_announce(UCHAR * ptr,NX_PTP_CLIENT_MASTER * master)477 static VOID _nx_ptp_msg_parse_announce(UCHAR *ptr, NX_PTP_CLIENT_MASTER *master)
478 {
479     ptr += NX_PTP_MSG_TIMESTAMP_LEN + 2 + 1; /* originTimestamp, utcOffset, reserved */
480     master -> nx_ptp_client_master_priority1 = *ptr++;
481     master -> nx_ptp_client_master_clock_class = *ptr++;
482     master -> nx_ptp_client_master_clock_accuracy = *ptr++;
483     NX_PTP_RD16(ptr, master -> nx_ptp_client_master_offset_scaled_log_variance);
484     master -> nx_ptp_client_master_priority2 = *ptr++;
485     master -> nx_ptp_client_master_grandmaster_identity = ptr;
486     ptr += NX_PTP_CLOCK_IDENTITY_SIZE;
487     NX_PTP_RD16(ptr, master -> nx_ptp_client_master_steps_removed);
488     master -> nx_ptp_client_master_time_source = *ptr;
489 }
490 
491 #ifdef NX_PTP_ENABLE_MASTER
492 /**************************************************************************/
493 /*                                                                        */
494 /*  FUNCTION                                               RELEASE        */
495 /*                                                                        */
496 /*    _nx_ptp_client_master_clock_compare                    PORTABLE C   */
497 /*                                                           6.4.0        */
498 /*  AUTHOR                                                                */
499 /*                                                                        */
500 /*    Tiejun Zhou, Microsoft Corporation                                  */
501 /*                                                                        */
502 /*  DESCRIPTION                                                           */
503 /*                                                                        */
504 /*    This function compares two clocks for master1 and master2.          */
505 /*                                                                        */
506 /*  INPUT                                                                 */
507 /*                                                                        */
508 /*    master1                               Pointer to first master clock */
509 /*    master2                               Pointer to second master clock*/
510 /*                                                                        */
511 /*  OUTPUT                                                                */
512 /*                                                                        */
513 /*    Compare result.                                                      */
514 /*    Return positive if master1 is better than master2.                  */
515 /*    Return zero if master1 is identical to master2.                     */
516 /*    Return negative if master1 is worse than master2.                   */
517 /*                                                                        */
518 /*  CALLS                                                                 */
519 /*                                                                        */
520 /*    memcmp                                Compare memory                */
521 /*                                                                        */
522 /*  CALLED BY                                                             */
523 /*                                                                        */
524 /*    _nx_ptp_client_init_packet_received   Process PTP announce message  */
525 /*                                                                        */
526 /*  RELEASE HISTORY                                                       */
527 /*                                                                        */
528 /*    DATE              NAME                      DESCRIPTION             */
529 /*                                                                        */
530 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
531 /*                                                                        */
532 /**************************************************************************/
_nx_ptp_client_master_clock_compare(NX_PTP_CLIENT_MASTER * master1,NX_PTP_CLIENT_MASTER * master2)533 static INT _nx_ptp_client_master_clock_compare(NX_PTP_CLIENT_MASTER *master1, NX_PTP_CLIENT_MASTER *master2)
534 {
535 INT result;
536 INT gm_compare;
537 
538     gm_compare = memcmp(master2 -> nx_ptp_client_master_grandmaster_identity,
539                         master1 -> nx_ptp_client_master_grandmaster_identity,
540                         NX_PTP_CLOCK_IDENTITY_SIZE);
541     if (gm_compare == 0)
542     {
543 
544         /* Clock identical.  */
545         return(0);
546     }
547 
548     result = (INT)master2 -> nx_ptp_client_master_priority1 -
549              (INT)master1 -> nx_ptp_client_master_priority1;
550     if (result != 0)
551     {
552         return(result);
553     }
554 
555     result = (INT)master2 -> nx_ptp_client_master_clock_class -
556              (INT)master1 -> nx_ptp_client_master_clock_class;
557     if (result != 0)
558     {
559         return(result);
560     }
561 
562     result = (INT)master2 -> nx_ptp_client_master_clock_accuracy -
563              (INT)master1 -> nx_ptp_client_master_clock_accuracy;
564     if (result != 0)
565     {
566         return(result);
567     }
568 
569     result = (INT)master2 -> nx_ptp_client_master_offset_scaled_log_variance -
570              (INT)master1 -> nx_ptp_client_master_offset_scaled_log_variance;
571     if (result != 0)
572     {
573         return(result);
574     }
575 
576     result = (INT)master2 -> nx_ptp_client_master_priority2 -
577              (INT)master1 -> nx_ptp_client_master_priority2;
578     if (result != 0)
579     {
580         return(result);
581     }
582 
583     return(gm_compare);
584 }
585 #endif /* NX_PTP_ENABLE_MASTER */
586 
587 
588 /**************************************************************************/
589 /*                                                                        */
590 /*  FUNCTION                                               RELEASE        */
591 /*                                                                        */
592 /*    _nx_ptp_client_soft_clock_adjust                    PORTABLE C      */
593 /*                                                           6.1.3        */
594 /*  AUTHOR                                                                */
595 /*                                                                        */
596 /*    Yuxin Zhou, Microsoft Corporation                                   */
597 /*                                                                        */
598 /*  DESCRIPTION                                                           */
599 /*                                                                        */
600 /*    This function adjusts the value of the soft PTP clock.              */
601 /*                                                                        */
602 /*  INPUT                                                                 */
603 /*                                                                        */
604 /*    ptp_instance                          Pointer to PTP client         */
605 /*    offset_ns                             Signed number of nanoseconds  */
606 /*                                            to add to the PTP clock     */
607 /*                                                                        */
608 /*  OUTPUT                                                                */
609 /*                                                                        */
610 /*    None                                                                */
611 /*                                                                        */
612 /*  CALLS                                                                 */
613 /*                                                                        */
614 /*    _nx_ptp_client_utility_inc64          Increment a 64-bit number     */
615 /*    _nx_ptp_client_utility_dec64          Decrement a 64-bit number     */
616 /*                                                                        */
617 /*  CALLED BY                                                             */
618 /*                                                                        */
619 /*    _nx_ptp_client_soft_clock_callback    Soft PTP clock                */
620 /*                                                                        */
621 /*  RELEASE HISTORY                                                       */
622 /*                                                                        */
623 /*    DATE              NAME                      DESCRIPTION             */
624 /*                                                                        */
625 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
626 /*                                                                        */
627 /**************************************************************************/
_nx_ptp_client_soft_clock_adjust(VOID * ptp_instance,LONG offset_ns)628 static VOID _nx_ptp_client_soft_clock_adjust(VOID *ptp_instance, LONG offset_ns)
629 {
630 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
631 TX_INTERRUPT_SAVE_AREA
632 
633     /* enforce min/max values of offset */
634     if (offset_ns > NX_PTP_NANOSECONDS_PER_SEC)
635     {
636         offset_ns = NX_PTP_NANOSECONDS_PER_SEC;
637     }
638     else if (offset_ns < -NX_PTP_NANOSECONDS_PER_SEC)
639     {
640         offset_ns = -NX_PTP_NANOSECONDS_PER_SEC;
641     }
642 
643     /* add the number of nanosecond to the current time */
644     TX_DISABLE
645     client_ptr -> nx_ptp_client_soft_clock.nanosecond += offset_ns;
646     if (client_ptr -> nx_ptp_client_soft_clock.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
647     {
648         client_ptr -> nx_ptp_client_soft_clock.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
649         _nx_ptp_client_utility_inc64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
650                                      &client_ptr -> nx_ptp_client_soft_clock.second_low);
651     }
652     else if (client_ptr -> nx_ptp_client_soft_clock.nanosecond < 0)
653     {
654         client_ptr -> nx_ptp_client_soft_clock.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
655         _nx_ptp_client_utility_dec64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
656                                      &client_ptr -> nx_ptp_client_soft_clock.second_low);
657     }
658     TX_RESTORE
659 }
660 
661 
662 /**************************************************************************/
663 /*                                                                        */
664 /*  FUNCTION                                               RELEASE        */
665 /*                                                                        */
666 /*    _nx_ptp_client_timer_handler                        PORTABLE C      */
667 /*                                                           6.1.3        */
668 /*  AUTHOR                                                                */
669 /*                                                                        */
670 /*    Yuxin Zhou, Microsoft Corporation                                   */
671 /*                                                                        */
672 /*  DESCRIPTION                                                           */
673 /*                                                                        */
674 /*    This function implements the PTP client timer handler.              */
675 /*                                                                        */
676 /*  INPUT                                                                 */
677 /*                                                                        */
678 /*    ptp_instance                          Pointer to PTP client         */
679 /*                                                                        */
680 /*  OUTPUT                                                                */
681 /*                                                                        */
682 /*    None                                                                */
683 /*                                                                        */
684 /*  CALLS                                                                 */
685 /*                                                                        */
686 /*    tx_event_flags_set                    Set PTP timer event           */
687 /*                                                                        */
688 /*  CALLED BY                                                             */
689 /*                                                                        */
690 /*    ThreadX Timer                                                       */
691 /*                                                                        */
692 /*  RELEASE HISTORY                                                       */
693 /*                                                                        */
694 /*    DATE              NAME                      DESCRIPTION             */
695 /*                                                                        */
696 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
697 /*                                                                        */
698 /**************************************************************************/
_nx_ptp_client_timer_handler(ULONG ptp_instance)699 static VOID _nx_ptp_client_timer_handler(ULONG ptp_instance)
700 {
701 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
702 
703     /* Update soft timer.  */
704     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE,
705                                                &client_ptr -> nx_ptp_client_soft_clock, NX_NULL,
706                                                client_ptr -> nx_ptp_client_clock_callback_data);
707 
708     /* set timer event */
709     tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_TIMER_EVENT, TX_OR);
710 }
711 
712 
713 #if NX_PTP_CLIENT_TRANSPORT_UDP
714 /**************************************************************************/
715 /*                                                                        */
716 /*  FUNCTION                                               RELEASE        */
717 /*                                                                        */
718 /*    _nx_ptp_client_socket_receive_notify                PORTABLE C      */
719 /*                                                           6.1.3        */
720 /*  AUTHOR                                                                */
721 /*                                                                        */
722 /*    Yuxin Zhou, Microsoft Corporation                                   */
723 /*                                                                        */
724 /*  DESCRIPTION                                                           */
725 /*                                                                        */
726 /*    This function is invoked when UDP packet is received.               */
727 /*                                                                        */
728 /*  INPUT                                                                 */
729 /*                                                                        */
730 /*    socket_ptr                            Pointer to general socket     */
731 /*                                                                        */
732 /*  OUTPUT                                                                */
733 /*                                                                        */
734 /*    None                                                                */
735 /*                                                                        */
736 /*  CALLS                                                                 */
737 /*                                                                        */
738 /*    tx_event_flags_set                    Set UDP receive event         */
739 /*                                                                        */
740 /*  CALLED BY                                                             */
741 /*                                                                        */
742 /*    NetX UDP                                                            */
743 /*                                                                        */
744 /*  RELEASE HISTORY                                                       */
745 /*                                                                        */
746 /*    DATE              NAME                      DESCRIPTION             */
747 /*                                                                        */
748 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
749 /*                                                                        */
750 /**************************************************************************/
_nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET * socket_ptr)751 static VOID _nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET *socket_ptr)
752 {
753 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)(socket_ptr -> nx_udp_socket_reserved_ptr);
754 
755     /* set timer event */
756     tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR);
757 }
758 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
759 
760 
761 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
762 /**************************************************************************/
763 /*                                                                        */
764 /*  FUNCTION                                               RELEASE        */
765 /*                                                                        */
766 /*    _nx_ptp_client_ethernet_receive_notify              PORTABLE C      */
767 /*                                                           6.4.0        */
768 /*  AUTHOR                                                                */
769 /*                                                                        */
770 /*    Tiejun Zhou, Microsoft Corporation                                  */
771 /*                                                                        */
772 /*  DESCRIPTION                                                           */
773 /*                                                                        */
774 /*    This function is invoked when a packet is received.                 */
775 /*                                                                        */
776 /*  INPUT                                                                 */
777 /*                                                                        */
778 /*                                                                        */
779 /*                                                                        */
780 /*  OUTPUT                                                                */
781 /*                                                                        */
782 /*    None                                                                */
783 /*                                                                        */
784 /*  CALLS                                                                 */
785 /*                                                                        */
786 /*    tx_event_flags_set                    Set receive event             */
787 /*                                                                        */
788 /*  CALLED BY                                                             */
789 /*                                                                        */
790 /*    NetX link layer                                                     */
791 /*                                                                        */
792 /*  RELEASE HISTORY                                                       */
793 /*                                                                        */
794 /*    DATE              NAME                      DESCRIPTION             */
795 /*                                                                        */
796 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
797 /*                                                                        */
798 /**************************************************************************/
_nx_ptp_client_ethernet_receive_notify(NX_IP * ip_ptr,UINT interface_index,NX_PACKET * packet_ptr,ULONG physical_address_msw,ULONG physical_address_lsw,UINT packet_type,UINT header_size,VOID * context,struct NX_LINK_TIME_STRUCT * time_ptr)799 static UINT _nx_ptp_client_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
800                                                    ULONG physical_address_msw, ULONG physical_address_lsw,
801                                                    UINT packet_type, UINT header_size, VOID *context,
802                                                    struct NX_LINK_TIME_STRUCT *time_ptr)
803 {
804 TX_INTERRUPT_SAVE_AREA
805 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)context;
806 
807     NX_PARAMETER_NOT_USED(ip_ptr);
808     NX_PARAMETER_NOT_USED(interface_index);
809     NX_PARAMETER_NOT_USED(physical_address_msw);
810     NX_PARAMETER_NOT_USED(physical_address_lsw);
811     NX_PARAMETER_NOT_USED(packet_type);
812     NX_PARAMETER_NOT_USED(time_ptr);
813 
814     /* Clean off the Ethernet header.  */
815     packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + header_size;
816 
817     /* Adjust the packet length.  */
818     packet_ptr -> nx_packet_length =  packet_ptr -> nx_packet_length - header_size;
819 
820     /* Disable interrupts.  */
821     TX_DISABLE
822 
823     /* Check to see if the receive queue is empty.  */
824     if (client_ptr -> nx_ptp_client_received_packet_head)
825     {
826 
827         /* Not empty, just place the packet at the end of the queue.  */
828         (client_ptr -> nx_ptp_client_received_packet_tail) -> nx_packet_queue_next =  packet_ptr;
829         packet_ptr -> nx_packet_queue_next =  NX_NULL;
830         client_ptr -> nx_ptp_client_received_packet_tail =  packet_ptr;
831 
832         /* Restore interrupts.  */
833         TX_RESTORE
834     }
835     else
836     {
837 
838         /* Empty receive processing queue.  */
839         client_ptr -> nx_ptp_client_received_packet_head =  packet_ptr;
840         client_ptr -> nx_ptp_client_received_packet_tail =  packet_ptr;
841         packet_ptr -> nx_packet_queue_next =             NX_NULL;
842 
843         /* Restore interrupts.  */
844         TX_RESTORE
845 
846         /* set timer event */
847         tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR);
848     }
849     return(NX_SUCCESS);
850 }
851 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
852 
853 
854 #ifndef NX_PTP_DISABLE_SLAVE
855 /**************************************************************************/
856 /*                                                                        */
857 /*  FUNCTION                                               RELEASE        */
858 /*                                                                        */
859 /*    _nx_ptp_client_clock_adjust                         PORTABLE C      */
860 /*                                                           6.4.0        */
861 /*  AUTHOR                                                                */
862 /*                                                                        */
863 /*    Yuxin Zhou, Microsoft Corporation                                   */
864 /*                                                                        */
865 /*  DESCRIPTION                                                           */
866 /*                                                                        */
867 /*    Adjust the PTP clock with the given offset                          */
868 /*    If the offset is greater than one second, the clock is updated,     */
869 /*    otherwise it is adjusted with the number of nanoseconds.            */
870 /*                                                                        */
871 /*  INPUT                                                                 */
872 /*                                                                        */
873 /*    client_ptr                            Pointer to PTP client         */
874 /*    offset_ptr                            Pointer to time offset        */
875 /*                                                                        */
876 /*  OUTPUT                                                                */
877 /*                                                                        */
878 /*    None                                                                */
879 /*                                                                        */
880 /*  CALLS                                                                 */
881 /*                                                                        */
882 /*    _nx_ptp_client_utility_inc64          Increment a 64-bit number     */
883 /*    _nx_ptp_client_utility_dec64          Decrement a 64-bit number     */
884 /*    _nx_ptp_client_utility_add64          Add two 64-bit number         */
885 /*                                                                        */
886 /*  CALLED BY                                                             */
887 /*                                                                        */
888 /*    _nx_ptp_client_delay_resp_received    Process delay response        */
889 /*                                                                        */
890 /*  RELEASE HISTORY                                                       */
891 /*                                                                        */
892 /*    DATE              NAME                      DESCRIPTION             */
893 /*                                                                        */
894 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
895 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
896 /*                                            supported master clock,     */
897 /*                                            resulting in version 6.4.0  */
898 /*                                                                        */
899 /**************************************************************************/
_nx_ptp_client_clock_adjust(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * offset_ptr)900 static VOID _nx_ptp_client_clock_adjust(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *offset_ptr)
901 {
902 NX_PTP_TIME current;
903 
904     if ((offset_ptr -> second_high == 0) && (offset_ptr -> second_low == 0))
905     {
906 
907         /* offset less than 1s, adjust clock */
908         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_ADJUST, offset_ptr, NX_NULL,
909                                                    client_ptr -> nx_ptp_client_clock_callback_data);
910         NX_PTP_DEBUG_PRINTF(("PTP: adjust clock %d ns\r\n", (INT)offset_ptr -> nanosecond));
911     }
912     else
913     {
914 
915         /* offset greater than 1s, set new clock value */
916         /* get current clock value */
917         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, &current, NX_NULL,
918                                                    client_ptr -> nx_ptp_client_clock_callback_data);
919 
920         /* add nanoseconds offset */
921         current.nanosecond += offset_ptr -> nanosecond;
922 
923         /* ensure nanosecond field is in range 0-999999999 */
924         if (current.nanosecond < 0)
925         {
926             current.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
927             _nx_ptp_client_utility_dec64(&current.second_high, &current.second_low);
928         }
929         else if (current.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
930         {
931             current.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
932             _nx_ptp_client_utility_inc64(&current.second_high, &current.second_low);
933         }
934 
935         /* add seconds offset */
936         _nx_ptp_client_utility_add64(&current.second_high, &current.second_low,
937                                      offset_ptr -> second_high, offset_ptr -> second_low);
938 
939         /* set new clock value */
940         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, &current, NX_NULL,
941                                                    client_ptr -> nx_ptp_client_clock_callback_data);
942 
943         NX_PTP_DEBUG_PRINTF(("PTP: set clock %u.%d\r\n",
944                             (UINT)current.second_low,
945                             (INT)current.nanosecond));
946     }
947 
948 #if defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
949     if (client_ptr -> nx_ptp_client_sync_timer == 0)
950     {
951 
952         /* Set timer values */
953         client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
954     }
955 #endif /* defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC) */
956 }
957 #endif
958 
959 #if NX_PTP_CLIENT_TRANSPORT_UDP
960 /**************************************************************************/
961 /*                                                                        */
962 /*  FUNCTION                                               RELEASE        */
963 /*                                                                        */
964 /*    _nx_ptp_client_send_delay_req                       PORTABLE C      */
965 /*                                                           6.4.0        */
966 /*  AUTHOR                                                                */
967 /*                                                                        */
968 /*    Yuxin Zhou, Microsoft Corporation                                   */
969 /*                                                                        */
970 /*  DESCRIPTION                                                           */
971 /*                                                                        */
972 /*    This function sends a PTP Delay Request message.                    */
973 /*                                                                        */
974 /*  INPUT                                                                 */
975 /*                                                                        */
976 /*    client_ptr                            Pointer to PTP client         */
977 /*                                                                        */
978 /*  OUTPUT                                                                */
979 /*                                                                        */
980 /*    None                                                                */
981 /*                                                                        */
982 /*  CALLS                                                                 */
983 /*                                                                        */
984 /*    nx_packet_allocate                    Allocate a packet             */
985 /*    nxd_udp_socket_source_send            Send a UDP packet             */
986 /*    nx_packet_release                     Release a packet              */
987 /*                                                                        */
988 /*  CALLED BY                                                             */
989 /*                                                                        */
990 /*    _nx_ptp_client_sync_received          Process Sync message          */
991 /*                                                                        */
992 /*  RELEASE HISTORY                                                       */
993 /*                                                                        */
994 /*    DATE              NAME                      DESCRIPTION             */
995 /*                                                                        */
996 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
997 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
998 /*                                            supported gPTP profile,     */
999 /*                                            supported master clock,     */
1000 /*                                            resulting in version 6.4.0  */
1001 /*                                                                        */
1002 /**************************************************************************/
_nx_ptp_client_send_delay_req(NX_PTP_CLIENT * client_ptr)1003 static VOID _nx_ptp_client_send_delay_req(NX_PTP_CLIENT *client_ptr)
1004 {
1005 NX_PACKET        *packet_ptr;
1006 UINT              status = NX_NOT_SUCCESSFUL;
1007 UCHAR            *ptr;
1008 #if NX_PTP_CLIENT_TRANSPORT_UDP
1009 NXD_ADDRESS       addr;
1010 UINT              addr_index = 0;
1011 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
1012 NXD_IPV6_ADDRESS *ipv6_addr;
1013 NX_IP            *ip_ptr;
1014 NX_INTERFACE     *if_ptr;
1015 #endif
1016 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1017 
1018     /* allocate a packet from the pool */
1019     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
1020     if (status != NX_SUCCESS)
1021     {
1022         /* Failed to allocate the packet */
1023         return;
1024     }
1025 
1026     /* start of message */
1027     ptr = packet_ptr -> nx_packet_prepend_ptr;
1028 
1029 #define PTP_MSG_DELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN)
1030 #define PTP_MSG_DELAY_REQ_ZERO1_LEN (1 + 2 + 8 + 4) /* reserved(1) | flagField(2) | correctionField(8) | reserved(4) */
1031 
1032     /* write header */
1033     *ptr++ = NX_PTP_MSG_TYPE_DELAY_REQ;
1034     *ptr++ = NX_PTP_VERSION;
1035     *ptr++ = PTP_MSG_DELAY_REQ_TOTAL_LEN >> 8;
1036     *ptr++ = (UCHAR)PTP_MSG_DELAY_REQ_TOTAL_LEN;
1037     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | client_ptr -> nx_ptp_client_domain;
1038     memset(ptr, 0, PTP_MSG_DELAY_REQ_ZERO1_LEN); /* reserved/flags/correction/reserved */
1039     ptr += PTP_MSG_DELAY_REQ_ZERO1_LEN;
1040     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity,
1041            NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
1042     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
1043     client_ptr -> nx_ptp_client_delay_req_id++;
1044     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_delay_req_id >> 8);
1045     *ptr++ = (UCHAR)client_ptr -> nx_ptp_client_delay_req_id;
1046     *ptr++ = 0; /* control */
1047     *ptr++ = 0; /* XXX */
1048 
1049     /* write timestamp (0) */
1050     memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
1051     ptr += NX_PTP_MSG_TIMESTAMP_LEN;
1052 
1053     /* set final length of message */
1054     packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr);
1055     packet_ptr -> nx_packet_append_ptr = ptr;
1056 
1057 #if NX_PTP_CLIENT_TRANSPORT_UDP
1058     /* set source and destination addresses */
1059 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
1060     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
1061     {
1062         NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
1063 
1064         /* Use first IPv6 address as source address. */
1065         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
1066         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
1067         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
1068         if (ipv6_addr == NX_NULL)
1069         {
1070 
1071             /* No available IPv6 address.  */
1072             /* Release packet.  */
1073             nx_packet_release(packet_ptr);
1074 
1075             /* Reset state.  */
1076             client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1077             client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
1078 
1079             return;
1080         }
1081         addr_index = ipv6_addr -> nxd_ipv6_address_index;
1082     }
1083     else
1084 #endif
1085     {
1086 #ifndef NX_DISABLE_IPV4
1087         addr.nxd_ip_version = NX_IP_VERSION_V4;
1088         addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
1089         addr_index = client_ptr -> nx_ptp_client_interface_index;
1090 #endif
1091     }
1092 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1093 
1094     /* Prepare timestamp for current packet  */
1095     client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_REQ_TS;
1096     client_ptr -> nx_ptp_client_delay_req_packet_ptr = packet_ptr;
1097     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
1098                                                &client_ptr -> nx_ptp_client_delay_ts, packet_ptr,
1099                                                client_ptr -> nx_ptp_client_clock_callback_data);
1100 
1101     /* Send delay request  */
1102 #if NX_PTP_CLIENT_TRANSPORT_UDP
1103     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
1104                                         packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index);
1105 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1106 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
1107     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
1108                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
1109                                  NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_MSB,
1110                                  NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_LSB,
1111                                  NX_PTP_ETHERNET_TYPE);
1112 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
1113     if (status)
1114     {
1115 
1116         /* release packet in case of error */
1117         nx_packet_release(packet_ptr);
1118 
1119         /* reset state */
1120         client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1121         client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
1122 
1123         return;
1124     }
1125 
1126     /* rearm delay req timer */
1127     client_ptr -> nx_ptp_client_delay_req_timer = NX_PTP_CLIENT_DELAY_REQ_INTERVAL;
1128     client_ptr -> nx_ptp_client_delay_req_flag = 0;
1129 }
1130 #endif
1131 
1132 /**************************************************************************/
1133 /*                                                                        */
1134 /*  FUNCTION                                               RELEASE        */
1135 /*                                                                        */
1136 /*    _nx_ptp_client_sync_received                        PORTABLE C      */
1137 /*                                                           6.4.0        */
1138 /*  AUTHOR                                                                */
1139 /*                                                                        */
1140 /*    Yuxin Zhou, Microsoft Corporation                                   */
1141 /*                                                                        */
1142 /*  DESCRIPTION                                                           */
1143 /*                                                                        */
1144 /*    This function processes a received PTP Sync message.                */
1145 /*                                                                        */
1146 /*  INPUT                                                                 */
1147 /*                                                                        */
1148 /*    client_ptr                            Pointer to PTP client         */
1149 /*    ts_ptr                                Pointer to the timestamp      */
1150 /*                                           delivered by the Sync message*/
1151 /*    hdr                                   Pointer to PTP header         */
1152 /*                                                                        */
1153 /*  OUTPUT                                                                */
1154 /*                                                                        */
1155 /*    None                                                                */
1156 /*                                                                        */
1157 /*  CALLS                                                                 */
1158 /*                                                                        */
1159 /*    _nx_ptp_msg_parse_timestamp           Parse timestamp field         */
1160 /*    _nx_ptp_client_send_delay_req         Send delay request            */
1161 /*                                                                        */
1162 /*  CALLED BY                                                             */
1163 /*                                                                        */
1164 /*    _nx_ptp_client_process_event_packet   Process PTP event packet      */
1165 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
1166 /*                                                                        */
1167 /*  RELEASE HISTORY                                                       */
1168 /*                                                                        */
1169 /*    DATE              NAME                      DESCRIPTION             */
1170 /*                                                                        */
1171 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
1172 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
1173 /*                                            supported gPTP profile,     */
1174 /*                                            supported master clock,     */
1175 /*                                            resulting in version 6.4.0  */
1176 /*                                                                        */
1177 /**************************************************************************/
_nx_ptp_client_sync_received(NX_PTP_CLIENT * client_ptr,VOID * ts_ptr,NX_PTP_MSG_HEADER * hdr)1178 static VOID _nx_ptp_client_sync_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr, NX_PTP_MSG_HEADER *hdr)
1179 {
1180 #if defined NX_ENABLE_GPTP
1181 NX_PTP_TIME offset;
1182 #ifndef NX_PTP_DISABLE_SLAVE
1183 NX_PTP_CLIENT_SYNC sync;
1184 #endif /* NX_PTP_DISABLE_SLAVE */
1185 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
1186 double      rate_ratio;
1187 NX_PTP_TIME delta_t1, delta_t2;
1188 #endif
1189 #endif /* NX_ENABLE_GPTP */
1190 NX_PTP_TIME correction;
1191 ULONG64     correctionNS = (hdr -> cFieldHigh << 16) | (hdr -> cFieldLow >> 16);
1192 
1193     /* store Sync master timestamp */
1194     _nx_ptp_msg_parse_timestamp(ts_ptr, &client_ptr -> nx_ptp_client_sync);
1195 
1196     if (correctionNS != 0)
1197     {
1198 
1199         /* add correction field to offset.  */
1200         correction.second_high = 0;
1201         correction.second_low = (ULONG)(correctionNS / 1000000000);
1202         correction.nanosecond = (LONG)(correctionNS % 1000000000);
1203         _nx_ptp_client_utility_time_sum(&client_ptr -> nx_ptp_client_sync, &correction,
1204                                         &client_ptr -> nx_ptp_client_sync);
1205     }
1206 
1207 #if defined NX_ENABLE_GPTP
1208 
1209     if ((client_ptr -> nx_ptp_client_delay.nanosecond > NX_PTP_CLIENT_DELAY_THRESH) ||
1210         (client_ptr -> nx_ptp_client_delay.second_low != 0) ||
1211         (client_ptr -> nx_ptp_client_delay.second_high != 0))
1212     {
1213 
1214         /* Not as capable. IEEE802.1AS-202, 11.2.2. */
1215         return;
1216     }
1217 
1218 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
1219     /* Compute neighbor rate ratio.
1220        neighborRateRatio = (t1 - prev_t1) / (t2 - prev_t2) */
1221     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync,
1222                                      &client_ptr -> nx_ptp_client_prev_sync, &delta_t1);
1223     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts,
1224                                      &client_ptr -> nx_ptp_client_prev_sync_ts, &delta_t2);
1225     if ((delta_t1.second_low == 0) && (delta_t1.second_high == 0) &&
1226         (delta_t2.second_low == 0) && (delta_t2.second_high == 0))
1227     {
1228         rate_ratio = (double)delta_t1.nanosecond / (double)delta_t2.nanosecond;
1229     }
1230     else
1231     {
1232         rate_ratio = 1.0;
1233     }
1234     NX_PTP_DEBUG_PRINTF(("PTP: neighborRateRatio = %lu/%lu = %f\n",
1235                          delta_t1.nanosecond, delta_t2.nanosecond, rate_ratio));
1236 #endif
1237 
1238     /* compute offset = sync_ts - sync_received_ts + delay */
1239     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync, &client_ptr -> nx_ptp_client_sync_ts, &offset);
1240     _nx_ptp_client_utility_time_sum(&offset, &client_ptr -> nx_ptp_client_delay, &offset);
1241 
1242 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
1243     if ((offset.second_low == 0) && (offset.second_high == 0))
1244     {
1245         if ((offset.nanosecond > -1000) && (offset.nanosecond < 1000))
1246         {
1247             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld ns\n", offset.nanosecond));
1248         }
1249         else if ((offset.nanosecond > -1000000) && (offset.nanosecond < 1000000))
1250         {
1251             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld us\n", offset.nanosecond / 1000));
1252         }
1253         else
1254         {
1255             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld ms\n", offset.nanosecond / 1000000));
1256         }
1257     }
1258     else
1259     {
1260         NX_PTP_DEBUG_PRINTF(("PTP: offset > 1s\n"));
1261     }
1262 #endif
1263 
1264 #ifndef NX_PTP_DISABLE_SLAVE
1265     if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_SLAVE)
1266     {
1267 
1268         /* add the time offset the client clock */
1269         _nx_ptp_client_clock_adjust(client_ptr, &offset);
1270 
1271         /* set calibrated flag */
1272         if (!(client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED))
1273         {
1274             client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED;
1275 
1276             /* application callback */
1277             if (client_ptr -> nx_ptp_client_event_callback)
1278             {
1279                 sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags;
1280                 sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset;
1281                 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
1282                                                         client_ptr -> nx_ptp_client_event_callback_data);
1283             }
1284         }
1285     }
1286 #endif /* NX_PTP_DISABLE_SLAVE */
1287 
1288     /* update pdelay responder state */
1289     client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
1290 #else
1291     /* delay and offset determination */
1292     if (client_ptr -> nx_ptp_client_delay_req_flag)
1293     {
1294 
1295         /* send delay request message */
1296         /* (delay_req_flag is cleared by this function) */
1297         _nx_ptp_client_send_delay_req(client_ptr);
1298     }
1299 #endif
1300 }
1301 
1302 #if NX_PTP_CLIENT_TRANSPORT_UDP
1303 /**************************************************************************/
1304 /*                                                                        */
1305 /*  FUNCTION                                               RELEASE        */
1306 /*                                                                        */
1307 /*    _nx_ptp_client_delay_resp_received                  PORTABLE C      */
1308 /*                                                           6.4.0        */
1309 /*  AUTHOR                                                                */
1310 /*                                                                        */
1311 /*    Yuxin Zhou, Microsoft Corporation                                   */
1312 /*                                                                        */
1313 /*  DESCRIPTION                                                           */
1314 /*                                                                        */
1315 /*    This function processes a received PTP Delay Response message.      */
1316 /*                                                                        */
1317 /*  INPUT                                                                 */
1318 /*                                                                        */
1319 /*    client_ptr                            Pointer to PTP client         */
1320 /*    ts_ptr                                Pointer to the timestamp      */
1321 /*                                           delivered by the Delay Resp  */
1322 /*                                           message                      */
1323 /*                                                                        */
1324 /*  OUTPUT                                                                */
1325 /*                                                                        */
1326 /*    None                                                                */
1327 /*                                                                        */
1328 /*  CALLS                                                                 */
1329 /*                                                                        */
1330 /*    _nx_ptp_client_clock_adjust           Adjust PTP clock              */
1331 /*    _nx_ptp_msg_parse_timestamp           Parse timestamp field         */
1332 /*    _nx_ptp_client_utility_time_diff      Diff two PTP times            */
1333 /*    _nx_ptp_client_utility_time_div_by_2  Divide a PTP time by 2        */
1334 /*                                                                        */
1335 /*  CALLED BY                                                             */
1336 /*                                                                        */
1337 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
1338 /*                                                                        */
1339 /*  RELEASE HISTORY                                                       */
1340 /*                                                                        */
1341 /*    DATE              NAME                      DESCRIPTION             */
1342 /*                                                                        */
1343 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
1344 /*  03-02-2021     Yuxin Zhou               Modified comment(s), and      */
1345 /*                                            fixed compiler warnings,    */
1346 /*                                            resulting in version 6.1.5  */
1347 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
1348 /*                                            simplified debug output,    */
1349 /*                                            resulting in version 6.4.0  */
1350 /*                                                                        */
1351 /**************************************************************************/
_nx_ptp_client_delay_resp_received(NX_PTP_CLIENT * client_ptr,VOID * ts_ptr)1352 static VOID _nx_ptp_client_delay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
1353 {
1354 NX_PTP_TIME        t4, a, b;
1355 NX_PTP_CLIENT_SYNC sync;
1356 
1357     /*
1358      * The following timestamps are used for delay/offset determination:
1359      *
1360      * t1 = nx_ptp_client_sync
1361      * t2 = nx_ptp_client_sync_ts
1362      * t3 = nx_ptp_client_delay_ts
1363      * t4 = timestamp in Delay_Resp message (ts_ptr)
1364      *
1365      * A = t2 - t1
1366      * B = t4 - t3
1367      *
1368      * delay  = (A + B) / 2
1369      * offset = (B - A) / 2
1370      */
1371 
1372     /* check for valid timestamp t1 */
1373     if ((client_ptr -> nx_ptp_client_sync.second_low == 0) &&
1374         (client_ptr -> nx_ptp_client_sync.second_high == 0))
1375     {
1376         return;
1377     }
1378 
1379     /* get master clock timestamp */
1380     _nx_ptp_msg_parse_timestamp(ts_ptr, &t4);
1381 
1382     /* compute A = t2 - t1 */
1383     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts, &client_ptr -> nx_ptp_client_sync, &a);
1384 
1385     /* compute B = t4 - t3 */
1386     _nx_ptp_client_utility_time_diff(&t4, &client_ptr -> nx_ptp_client_delay_ts, &b);
1387 
1388     /* compute offset = (B - A) / 2 */
1389     _nx_ptp_client_utility_time_diff(&b, &a, &a);
1390     _nx_ptp_client_utility_time_div_by_2(&a);
1391 
1392 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
1393     if ((a.second_low == 0) && (a.second_high == 0))
1394     {
1395         if ((a.nanosecond > -1000) && (a.nanosecond < 1000))
1396         {
1397             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld ns\n", a.nanosecond));
1398         }
1399         else if ((a.nanosecond > -1000000) && (a.nanosecond < 1000000))
1400         {
1401             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld us\n", a.nanosecond / 1000));
1402         }
1403         else
1404         {
1405             NX_PTP_DEBUG_PRINTF(("PTP: offset = %ld ms\n", a.nanosecond / 1000000));
1406         }
1407     }
1408     else
1409     {
1410         NX_PTP_DEBUG_PRINTF(("PTP: offset > 1s\n"));
1411     }
1412 #endif
1413 
1414     /* add the time offset the client clock */
1415     _nx_ptp_client_clock_adjust(client_ptr, &a);
1416 
1417     /* set calibrated flag */
1418     if (!(client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED))
1419     {
1420 
1421         client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED;
1422 
1423         /* application callback */
1424         if (client_ptr -> nx_ptp_client_event_callback)
1425         {
1426             sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags;
1427             sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset;
1428             client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
1429                                                        client_ptr -> nx_ptp_client_event_callback_data);
1430         }
1431     }
1432 
1433     /* update delay req state */
1434     client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1435 }
1436 #endif
1437 
1438 /**************************************************************************/
1439 /*                                                                        */
1440 /*  FUNCTION                                               RELEASE        */
1441 /*                                                                        */
1442 /*    _nx_ptp_client_init_packet_received                 PORTABLE C      */
1443 /*                                                           6.4.0        */
1444 /*  AUTHOR                                                                */
1445 /*                                                                        */
1446 /*    Yuxin Zhou, Microsoft Corporation                                   */
1447 /*                                                                        */
1448 /*  DESCRIPTION                                                           */
1449 /*                                                                        */
1450 /*    This function processes a received PTP Announce message.            */
1451 /*                                                                        */
1452 /*  INPUT                                                                 */
1453 /*                                                                        */
1454 /*    client_ptr                            Pointer to PTP client         */
1455 /*    hdr                                   Pointer to PTP header         */
1456 /*    ptr                                   Pointer to PTP message        */
1457 /*                                                                        */
1458 /*  OUTPUT                                                                */
1459 /*                                                                        */
1460 /*    None                                                                */
1461 /*                                                                        */
1462 /*  CALLS                                                                 */
1463 /*                                                                        */
1464 /*    _nx_ptp_msg_parse_announce            Parse Announce message        */
1465 /*    memcpy                                Copy memory                   */
1466 /*                                                                        */
1467 /*  CALLED BY                                                             */
1468 /*                                                                        */
1469 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
1470 /*    _nx_ptp_client_master_clock_compare   Compare two master clocks     */
1471 /*                                                                        */
1472 /*  RELEASE HISTORY                                                       */
1473 /*                                                                        */
1474 /*    DATE              NAME                      DESCRIPTION             */
1475 /*                                                                        */
1476 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
1477 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
1478 /*                                            supported gPTP profile,     */
1479 /*                                            supported master clock,     */
1480 /*                                            resulting in version 6.4.0  */
1481 /*                                                                        */
1482 /**************************************************************************/
_nx_ptp_client_init_packet_received(NX_PTP_CLIENT * client_ptr,NX_PTP_MSG_HEADER * hdr,UCHAR * ptr)1483 static VOID _nx_ptp_client_init_packet_received(NX_PTP_CLIENT *client_ptr,
1484                                              NX_PTP_MSG_HEADER *hdr,
1485                                              UCHAR *ptr)
1486 {
1487 NX_PTP_CLIENT_SYNC   sync;
1488 NX_PTP_CLIENT_MASTER master;
1489 #ifdef NX_PTP_ENABLE_MASTER
1490 INT compare_result;
1491 
1492     if (client_ptr -> nx_ptp_client_role == NX_PTP_CLIENT_ROLE_MASTER_ONLY)
1493     {
1494 
1495         /* ignore announce packet for master only mode */
1496         return;
1497     }
1498 #endif /* NX_PTP_ENABLE_MASTER */
1499 
1500     /* parse Sync information */
1501     sync.nx_ptp_client_sync_flags = 0;
1502     if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE)
1503     {
1504         sync.nx_ptp_client_sync_flags |=  NX_PTP_CLIENT_SYNC_UTC_REASONABLE;
1505     }
1506     if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP59)
1507     {
1508         sync.nx_ptp_client_sync_flags |=  NX_PTP_CLIENT_SYNC_LEAP59;
1509     }
1510     if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP61)
1511     {
1512         sync.nx_ptp_client_sync_flags |=  NX_PTP_CLIENT_SYNC_LEAP61;
1513     }
1514     sync.nx_ptp_client_sync_utc_offset = NX_PTP_MSG_UTC_OFFSET(ptr);
1515 
1516     /* parse announce message */
1517     _nx_ptp_msg_parse_announce(ptr, &master);
1518 
1519 #ifdef NX_PTP_ENABLE_MASTER
1520     if (client_ptr -> nx_ptp_client_role == NX_PTP_CLIENT_ROLE_SLAVE_AND_MASTER)
1521     {
1522 
1523         /* compare local clock with incoming master */
1524         compare_result = _nx_ptp_client_master_clock_compare(&client_ptr -> ptp_master, &master);
1525         if (compare_result == 0)
1526         {
1527 
1528             /* error, ignore current announce message */
1529             return;
1530         }
1531         else if (compare_result > 0)
1532         {
1533 
1534             /* recommend local clock to be master */
1535             if (client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_MASTER)
1536             {
1537 
1538                 /* set timeout for announce and sync */
1539                 client_ptr -> ptp_master.nx_ptp_client_master_announce_timer = NX_PTP_CLIENT_ANNOUNCE_INTERVAL;
1540                 client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
1541                 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_MASTER;
1542                 NX_PTP_DEBUG_PRINTF(("PTP: recommend local clock to be master\r\n"));
1543 
1544                 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER,
1545                                                            &client_ptr -> ptp_master,
1546                                                            client_ptr -> nx_ptp_client_event_callback_data);
1547             }
1548             return;
1549         }
1550         else
1551         {
1552             /* recommend local clock to be slave */
1553             if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_MASTER)
1554             {
1555 
1556                 /* disable timers for announce and sync */
1557                 client_ptr -> ptp_master.nx_ptp_client_master_announce_timer = -1;
1558                 client_ptr -> nx_ptp_client_sync_timer = -1;
1559 
1560                 /* change the state to listening and then slave */
1561                 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
1562             }
1563         }
1564     }
1565 #endif /* NX_PTP_ENABLE_MASTER */
1566 
1567     /* check for new master */
1568     if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
1569     {
1570 
1571         /* first announce message, save master clock parameters */
1572         client_ptr -> nx_ptp_client_sync_flags = sync.nx_ptp_client_sync_flags;
1573         client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
1574         memcpy(client_ptr -> nx_ptp_client_master_port_identity, hdr -> sourcePortIdentity,
1575                NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
1576 
1577         /* wait for Sync message */
1578         client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_SLAVE;
1579         client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1580 #ifdef NX_ENABLE_GPTP
1581         client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_IDLE;
1582         client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_SYNC;
1583 #endif
1584         client_ptr -> nx_ptp_client_delay_req_timer = -1;
1585         client_ptr -> nx_ptp_client_delay_req_flag = 1;
1586 
1587         if (hdr -> messageType == NX_PTP_MSG_TYPE_ANNOUNCE)
1588         {
1589             /* call application callback */
1590             if (client_ptr -> nx_ptp_client_event_callback)
1591             {
1592                 master.nx_ptp_client_master_address = &(client_ptr -> nx_ptp_client_master_addr);
1593                 master.nx_ptp_client_master_port_identity = hdr -> sourcePortIdentity;
1594                 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER, &master,
1595                                                         client_ptr -> nx_ptp_client_event_callback_data);
1596             }
1597         }
1598 
1599         /* Reset previous sync timestamp.  */
1600         NX_PTP_TS_RESET(client_ptr -> nx_ptp_client_prev_sync);
1601         NX_PTP_TS_RESET(client_ptr -> nx_ptp_client_prev_sync_ts);
1602         NX_PTP_TS_RESET(client_ptr -> nx_ptp_client_sync);
1603         NX_PTP_TS_RESET(client_ptr -> nx_ptp_client_sync_ts);
1604     }
1605     else
1606     {
1607 
1608         /* check for UTC offset update or flags changes */
1609         if (((client_ptr -> nx_ptp_client_sync_flags & ~NX_PTP_CLIENT_SYNC_CALIBRATED) !=
1610               sync.nx_ptp_client_sync_flags) ||
1611              (client_ptr -> nx_ptp_client_utc_offset != sync.nx_ptp_client_sync_utc_offset))
1612         {
1613             client_ptr -> nx_ptp_client_sync_flags =
1614                 (USHORT)((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) |
1615                             sync.nx_ptp_client_sync_flags);
1616             client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
1617 
1618             /* call application callback */
1619             if ((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) &&
1620                 (client_ptr -> nx_ptp_client_event_callback))
1621             {
1622                 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
1623                                                            client_ptr -> nx_ptp_client_event_callback_data);
1624             }
1625         }
1626     }
1627 
1628     /* reset announce timer */
1629     client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION;
1630 }
1631 
1632 #ifdef NX_ENABLE_GPTP
1633 /**************************************************************************/
1634 /*                                                                        */
1635 /*  FUNCTION                                               RELEASE        */
1636 /*                                                                        */
1637 /*    _nx_ptp_client_send_pdelay_req                      PORTABLE C      */
1638 /*                                                           6.4.0        */
1639 /*  AUTHOR                                                                */
1640 /*                                                                        */
1641 /*    Tiejun Zhou, Microsoft Corporation                                  */
1642 /*                                                                        */
1643 /*  DESCRIPTION                                                           */
1644 /*                                                                        */
1645 /*    This function sends a PTP Pdelay Request message.                   */
1646 /*                                                                        */
1647 /*  INPUT                                                                 */
1648 /*                                                                        */
1649 /*    client_ptr                            Pointer to PTP client         */
1650 /*                                                                        */
1651 /*  OUTPUT                                                                */
1652 /*                                                                        */
1653 /*    None                                                                */
1654 /*                                                                        */
1655 /*  CALLS                                                                 */
1656 /*                                                                        */
1657 /*    nx_packet_allocate                    Allocate a packet             */
1658 /*    nxd_udp_socket_source_send            Send a UDP packet             */
1659 /*    nx_packet_release                     Release a packet              */
1660 /*                                                                        */
1661 /*  CALLED BY                                                             */
1662 /*                                                                        */
1663 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
1664 /*                                                                        */
1665 /*  RELEASE HISTORY                                                       */
1666 /*                                                                        */
1667 /*    DATE              NAME                      DESCRIPTION             */
1668 /*                                                                        */
1669 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
1670 /*                                                                        */
1671 /**************************************************************************/
_nx_ptp_client_send_pdelay_req(NX_PTP_CLIENT * client_ptr)1672 static VOID _nx_ptp_client_send_pdelay_req(NX_PTP_CLIENT *client_ptr)
1673 {
1674 NX_PACKET *packet_ptr;
1675 UINT       status = NX_NOT_SUCCESSFUL;
1676 UCHAR     *ptr;
1677 #if NX_PTP_CLIENT_TRANSPORT_UDP
1678 NXD_ADDRESS       addr;
1679 UINT              addr_index = 0;
1680 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
1681 NXD_IPV6_ADDRESS *ipv6_addr;
1682 NX_IP            *ip_ptr;
1683 NX_INTERFACE     *if_ptr;
1684 #endif
1685 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1686 
1687     /* Allocate a packet from the pool */
1688     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
1689     if (status != NX_SUCCESS)
1690     {
1691         /* Failed to allocate the packet */
1692         return;
1693     }
1694 
1695     /* Start of message */
1696     ptr = packet_ptr -> nx_packet_prepend_ptr;
1697 
1698 #define PTP_MSG_PDELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN + NX_PTP_MSG_PDELAY_RESERVED_LEN)
1699 
1700     /* Write header IEEE Std 1588-2008 Section 13.3.1*/
1701     /* messageType */
1702     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_PDELAY_REQ;
1703     /* versionPTP */
1704     *ptr++ = NX_PTP_VERSION;
1705     /* messageLength */
1706     *ptr++ = PTP_MSG_PDELAY_REQ_TOTAL_LEN >> 8;
1707     *ptr++ = (UCHAR)PTP_MSG_PDELAY_REQ_TOTAL_LEN;
1708     /* domainNumber */
1709     *ptr++ = client_ptr -> nx_ptp_client_domain;
1710 
1711     /* reserved 1 octets */
1712     *ptr++ = 0;
1713 
1714     /* flags 2 octets */
1715     *ptr++ = 0;
1716     *ptr++ = 0;
1717 
1718     /* correction + reserved 8 + 4 */
1719     memset(ptr, 0, 12);
1720     ptr += 12;
1721 
1722     /* sourcePortIdentity */
1723     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
1724     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
1725     /* sequenceID */
1726     client_ptr -> nx_ptp_client_pdelay_req_id++;
1727     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_req_id >> 8);
1728     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_req_id);
1729     /* control */
1730     *ptr++ = 5; /* other message */
1731     /* XXX */
1732     *ptr++ = 0;
1733 
1734     /* write timestamp */
1735     memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
1736     ptr += NX_PTP_MSG_TIMESTAMP_LEN;
1737 
1738     /* write space for reserved space to align size with pdelay_resp */
1739     memset(ptr, 0, NX_PTP_MSG_PDELAY_RESERVED_LEN);
1740     ptr += NX_PTP_MSG_PDELAY_RESERVED_LEN;
1741 
1742     /* set final message length */
1743     packet_ptr -> nx_packet_length = (ULONG)(ptr - (packet_ptr -> nx_packet_prepend_ptr));
1744     packet_ptr -> nx_packet_append_ptr = ptr;
1745 
1746 #if NX_PTP_CLIENT_TRANSPORT_UDP
1747     /* set source and destination addresses */
1748 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
1749     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
1750     {
1751         NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(&addr);
1752 
1753         /* Use first IPv6 address as source address. */
1754         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
1755         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
1756         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
1757         if (ipv6_addr == NX_NULL)
1758         {
1759 
1760             /* No available IPv6 address.  */
1761             /* Release packet.  */
1762             nx_packet_release(packet_ptr);
1763 
1764             /* Reset state.  */
1765             client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_IDLE;
1766             client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
1767 
1768             return;
1769         }
1770         addr_index = ipv6_addr -> nxd_ipv6_address_index;
1771     }
1772     else
1773 #endif
1774     {
1775 #ifndef NX_DISABLE_IPV4
1776         addr.nxd_ip_version = NX_IP_VERSION_V4;
1777         addr.nxd_ip_address.v4 = NX_PTP_IPV4_P2P_MULTICAST_ADDR;
1778         addr_index = client_ptr -> nx_ptp_client_interface_index;
1779 #endif
1780     }
1781 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1782 
1783     /* Prepare timestamp for current packet */
1784     client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ_TS;
1785     client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = packet_ptr;
1786     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
1787                                                &client_ptr -> nx_ptp_client_pdelay_req_ts, packet_ptr,
1788                                                client_ptr -> nx_ptp_client_clock_callback_data);
1789 
1790     /* Send Pdelay_Req */
1791 #if NX_PTP_CLIENT_TRANSPORT_UDP
1792     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
1793                                         packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index);
1794 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
1795 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
1796     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
1797                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
1798                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
1799                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
1800                                  NX_PTP_ETHERNET_TYPE);
1801 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
1802     if (status)
1803     {
1804 
1805         /* release packet in case of error */
1806         nx_packet_release(packet_ptr);
1807 
1808         /* reset state */
1809         client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_IDLE;
1810         client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
1811 
1812         return;
1813     }
1814 
1815     /* rearm delay req timer (use the client timer) */
1816     client_ptr -> nx_ptp_client_pdelay_req_timer = NX_PTP_CLIENT_PDELAY_REQ_INTERVAL;
1817 }
1818 
1819 
1820 /**************************************************************************/
1821 /*                                                                        */
1822 /*  FUNCTION                                               RELEASE        */
1823 /*                                                                        */
1824 /*    _nx_ptp_client_pdelay_resp_received                 PORTABLE C      */
1825 /*                                                           6.4.0        */
1826 /*  AUTHOR                                                                */
1827 /*                                                                        */
1828 /*    Tiejun Zhou, Microsoft Corporation                                  */
1829 /*                                                                        */
1830 /*  DESCRIPTION                                                           */
1831 /*                                                                        */
1832 /*    This function processes a received PTP Pdelay Response message.     */
1833 /*                                                                        */
1834 /*  INPUT                                                                 */
1835 /*                                                                        */
1836 /*    client_ptr                            Pointer to PTP client         */
1837 /*    ts_ptr                                Pointer to the timestamp      */
1838 /*                                           delivered by the Pdelay Resp */
1839 /*                                           message                      */
1840 /*                                                                        */
1841 /*  OUTPUT                                                                */
1842 /*                                                                        */
1843 /*    None                                                                */
1844 /*                                                                        */
1845 /*  CALLS                                                                 */
1846 /*                                                                        */
1847 /*    _nx_ptp_client_clock_adjust           Adjust PTP clock              */
1848 /*    _nx_ptp_msg_parse_timestamp           Parse timestamp field         */
1849 /*    _nx_ptp_client_utility_time_diff      Diff two PTP times            */
1850 /*    _nx_ptp_client_utility_time_div_by_2  Divide a PTP time by 2        */
1851 /*                                                                        */
1852 /*  CALLED BY                                                             */
1853 /*                                                                        */
1854 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
1855 /*    _nx_ptp_client_process_event_packet   Process PTP event packet      */
1856 /*                                                                        */
1857 /*  RELEASE HISTORY                                                       */
1858 /*                                                                        */
1859 /*    DATE              NAME                      DESCRIPTION             */
1860 /*                                                                        */
1861 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
1862 /*                                                                        */
1863 /**************************************************************************/
_nx_ptp_client_pdelay_resp_received(NX_PTP_CLIENT * client_ptr,VOID * ts_ptr)1864 static VOID _nx_ptp_client_pdelay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
1865 {
1866 NX_PTP_TIME a, b, c, d, t3;
1867 
1868     /*
1869     * The following timestamps are used to calculate the mean link delay using P2P
1870     * t1 = nx_ptp_client_pdelay_req_ts
1871     * t2 = nx_ptp_client_pdelay_req_receipt_ts (within pdelay_resp)
1872     * t3 = nx_ptp_client_pdelay_resp_origin_ts (within pdelay_resp_follow_up or ts_ptr)
1873     * t4 = (onestep: nx_ptp_client_pdelay_req_receipt_ts)/(twostep:nx_ptp_client_pdelay_resp_ts)
1874     *
1875     * C = t2 - t1
1876     * D = t4 - t3
1877     *
1878     * <meanLinkDelay> = [(t2 – t1) + (t4 – t3)]/2
1879     *
1880     * A = t1 - t2
1881     * B = t3 - t4
1882     *
1883     * offset = [(t1 - t2) - (t3 - t4)]/2
1884     *        = [B - A]/2
1885     *
1886     *
1887     * onestep: <meanLinkDelay> = [(t4 − t1) − <correctedPdelayRespCorrectionField>]/2
1888     * correctedPDelayRespCorrectionField = t3-t2 (turnaround time)
1889     *
1890     * onestep offset = (t4 + t1 - (nx_ptp_client_pdelay_req_receipt_ts * 2))/2
1891     * - the multiply by 2 is here because we are not yet parsing the correction field
1892     *
1893     * twostep offset = (t4 + t1 - (nx_ptp_client_pdelay_req_receipt_ts + ts_ptr))/2
1894     *
1895     * We will set <delayAsymmetry> to 0 unless a value is provided by the user
1896     *
1897     * delay_asymmetry = 0;
1898     * corrected_pdelay_resp = ingress <delayAsymmetry> + pdelay_resp_correction_field
1899     * corrected_pdelay_resp = delay_asymmetry + pdelay_resp_correction_field
1900     */
1901 
1902     /* get message timestamp */
1903     _nx_ptp_msg_parse_timestamp(ts_ptr, &t3);
1904 
1905     /* compute A = t1 - t2 */
1906     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_pdelay_req_ts, &client_ptr -> nx_ptp_client_pdelay_req_receipt_ts, &a);
1907 
1908     /* compute B = t3 - t4 */
1909     _nx_ptp_client_utility_time_diff(&t3, &client_ptr -> nx_ptp_client_pdelay_resp_ts, &b);
1910 
1911     /* compute C = t2 - t1 */
1912     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_pdelay_req_receipt_ts, &client_ptr -> nx_ptp_client_pdelay_req_ts, &c);
1913 
1914     /* compute D = t4 - t3 */
1915     _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_pdelay_resp_ts, &t3, &d);
1916 
1917     /* compute delay = (D + C) / 2 */
1918     _nx_ptp_client_utility_time_sum(&d, &c, &client_ptr -> nx_ptp_client_delay);
1919     _nx_ptp_client_utility_time_div_by_2(&client_ptr -> nx_ptp_client_delay);
1920 
1921 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_DELAY)
1922     if ((client_ptr -> nx_ptp_client_delay.second_low == 0) && (client_ptr -> nx_ptp_client_delay.second_high == 0))
1923     {
1924         if ((client_ptr -> nx_ptp_client_delay.nanosecond > -1000) &&
1925             (client_ptr -> nx_ptp_client_delay.nanosecond < 1000))
1926         {
1927             NX_PTP_DEBUG_PRINTF(("PTP: delay = %ld ns", client_ptr -> nx_ptp_client_delay.nanosecond));
1928         }
1929         else if ((client_ptr -> nx_ptp_client_delay.nanosecond > -1000000) &&
1930                  (client_ptr -> nx_ptp_client_delay.nanosecond < 1000000))
1931         {
1932             NX_PTP_DEBUG_PRINTF(("PTP: delay = %ld us", client_ptr -> nx_ptp_client_delay.nanosecond / 1000));
1933         }
1934         else
1935         {
1936             NX_PTP_DEBUG_PRINTF(("PTP: delay = %ld ms", client_ptr -> nx_ptp_client_delay.nanosecond / 1000000));
1937         }
1938     }
1939     else
1940     {
1941         NX_PTP_DEBUG_PRINTF(("PTP: delay > 1s"));
1942     }
1943 
1944     if (client_ptr -> nx_ptp_client_delay.nanosecond > NX_PTP_CLIENT_DELAY_THRESH)
1945     {
1946         NX_PTP_DEBUG_PRINTF((", asCapable is FALSE\n"));
1947     }
1948     else
1949     {
1950         NX_PTP_DEBUG_PRINTF((", asCapable is TRUE\n"));
1951     }
1952 #endif
1953 
1954     /* update pdelay req state */
1955     client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_IDLE;
1956 }
1957 
1958 
1959 /**************************************************************************/
1960 /*                                                                        */
1961 /*  FUNCTION                                               RELEASE        */
1962 /*                                                                        */
1963 /*    _nx_ptp_client_send_pdelay_resp_follow_up           PORTABLE C      */
1964 /*                                                           6.4.0        */
1965 /*  AUTHOR                                                                */
1966 /*                                                                        */
1967 /*    Tiejun Zhou, Microsoft Corporation                                  */
1968 /*                                                                        */
1969 /*  DESCRIPTION                                                           */
1970 /*                                                                        */
1971 /*    This function sends a PTP Pdelay response follow up message.        */
1972 /*                                                                        */
1973 /*  INPUT                                                                 */
1974 /*                                                                        */
1975 /*    client_ptr                            Pointer to PTP client         */
1976 /*                                                                        */
1977 /*  OUTPUT                                                                */
1978 /*                                                                        */
1979 /*    None                                                                */
1980 /*                                                                        */
1981 /*  CALLS                                                                 */
1982 /*                                                                        */
1983 /*    nx_packet_allocate                    Allocate a packet             */
1984 /*    nxd_udp_socket_source_send            Send a UDP packet             */
1985 /*    nx_packet_release                     Release a packet              */
1986 /*                                                                        */
1987 /*  CALLED BY                                                             */
1988 /*                                                                        */
1989 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
1990 /*                                                                        */
1991 /*  RELEASE HISTORY                                                       */
1992 /*                                                                        */
1993 /*    DATE              NAME                      DESCRIPTION             */
1994 /*                                                                        */
1995 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
1996 /*                                                                        */
1997 /**************************************************************************/
_nx_ptp_client_send_pdelay_resp_follow_up(NX_PTP_CLIENT * client_ptr)1998 static VOID _nx_ptp_client_send_pdelay_resp_follow_up(NX_PTP_CLIENT *client_ptr)
1999 {
2000 NX_PACKET *packet_ptr;
2001 UINT       status = NX_NOT_SUCCESSFUL;
2002 UCHAR     *ptr;
2003 #if NX_PTP_CLIENT_TRANSPORT_UDP
2004 NXD_ADDRESS       addr;
2005 UINT              addr_index = 0;
2006 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2007 NXD_IPV6_ADDRESS *ipv6_addr;
2008 NX_IP            *ip_ptr;
2009 NX_INTERFACE     *if_ptr;
2010 #endif
2011 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2012 
2013     /* Verify state */
2014     if (client_ptr -> nx_ptp_client_pdelay_responder_state != NX_PTP_CLIENT_PDELAY_SEND_FOLLOW_UP)
2015     {
2016         return;
2017     }
2018 
2019     /* Allocate a packet from the pool */
2020     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
2021     if (status != NX_SUCCESS)
2022     {
2023         /* Failed to allocate the packet */
2024         return;
2025     }
2026 
2027     /* Start of message */
2028     ptr = packet_ptr -> nx_packet_prepend_ptr;
2029 
2030 #define PTP_MSG_PDELAY_RESP_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN + NX_PTP_MSG_PDELAY_RESERVED_LEN)
2031 
2032     /* Write header IEEE Std 1588-2008 Section 13.3.1*/
2033     /* messageType */
2034     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP;
2035     /* versionPTP */
2036     *ptr++ = NX_PTP_VERSION;
2037     /* messageLength */
2038     *ptr++ = PTP_MSG_PDELAY_RESP_TOTAL_LEN >> 8;
2039     *ptr++ = (UCHAR)PTP_MSG_PDELAY_RESP_TOTAL_LEN;
2040     /* domainNumber */
2041     *ptr++ = client_ptr -> nx_ptp_client_domain;
2042     /* reserved 1 octets */
2043     *ptr++ = 0;
2044     /* flags 2 octets */
2045     *ptr++ = 0;
2046     *ptr++ = 0;
2047     /* correction + reserved 8 + 4 (correction field to be updated with t3-t2 later) */
2048     memset(ptr, 0, 12);
2049     ptr += 12;
2050     /* sourcePortIdentity */
2051     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2052     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2053     /* sequenceID */
2054     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_responder_id >> 8);
2055     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_responder_id);
2056     /* control */
2057     *ptr++ = 5; /* other message */
2058     /* XXX */
2059     *ptr++ = 0;
2060 
2061     /* write timestamp t3 */
2062     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_pdelay_resp_origin).second_high >> 8);
2063     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_pdelay_resp_origin).second_high);
2064     _nx_ptp_utility_32_unsigned_write(ptr, (client_ptr -> nx_ptp_client_pdelay_resp_origin).second_low);
2065     ptr += 4;
2066     _nx_ptp_utility_32_unsigned_write(ptr, (ULONG)(client_ptr -> nx_ptp_client_pdelay_resp_origin.nanosecond));
2067     ptr += 4;
2068 
2069     /* write requestingPortIdentity */
2070     memcpy(ptr, client_ptr -> nx_ptp_client_request_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2071     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2072 
2073     /* set final message length */
2074     packet_ptr -> nx_packet_length = (ULONG)(ptr - (packet_ptr -> nx_packet_prepend_ptr));
2075     packet_ptr -> nx_packet_append_ptr = ptr;
2076 
2077 #if NX_PTP_CLIENT_TRANSPORT_UDP
2078     /* set source and destination addresses */
2079 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2080     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
2081     {
2082         NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(&addr);
2083 
2084         /* Use first IPv6 address as source address. */
2085         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
2086         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
2087         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
2088         if (ipv6_addr == NX_NULL)
2089         {
2090 
2091             /* No available IPv6 address.  */
2092             /* Release packet.  */
2093             nx_packet_release(packet_ptr);
2094 
2095             /* Reset state.  */
2096             client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
2097             client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
2098 
2099             return;
2100         }
2101         addr_index = ipv6_addr -> nxd_ipv6_address_index;
2102     }
2103     else
2104 #endif
2105     {
2106 #ifndef NX_DISABLE_IPV4
2107         addr.nxd_ip_version = NX_IP_VERSION_V4;
2108         addr.nxd_ip_address.v4 = NX_PTP_IPV4_P2P_MULTICAST_ADDR;
2109         addr_index = client_ptr -> nx_ptp_client_interface_index;
2110 #endif
2111     }
2112 
2113     /* Send Pdelay_Resp */
2114     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
2115                                         packet_ptr, &addr, NX_PTP_GENERAL_UDP_PORT, addr_index);
2116 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2117 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
2118     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
2119                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
2120                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
2121                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
2122                                  NX_PTP_ETHERNET_TYPE);
2123 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
2124     if (status)
2125     {
2126         /* release packet in case of error */
2127         nx_packet_release(packet_ptr);
2128 
2129         /* reset state */
2130         client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
2131         client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
2132 
2133         return;
2134     }
2135 
2136     client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
2137 }
2138 
2139 
2140 /**************************************************************************/
2141 /*                                                                        */
2142 /*  FUNCTION                                               RELEASE        */
2143 /*                                                                        */
2144 /*    _nx_ptp_client_send_pdelay_resp                     PORTABLE C      */
2145 /*                                                           6.4.0        */
2146 /*  AUTHOR                                                                */
2147 /*                                                                        */
2148 /*    Tiejun Zhou, Microsoft Corporation                                  */
2149 /*                                                                        */
2150 /*  DESCRIPTION                                                           */
2151 /*                                                                        */
2152 /*    This function sends a PTP Pdelay response message.                  */
2153 /*                                                                        */
2154 /*  INPUT                                                                 */
2155 /*                                                                        */
2156 /*    client_ptr                            Pointer to PTP client         */
2157 /*                                                                        */
2158 /*  OUTPUT                                                                */
2159 /*                                                                        */
2160 /*    None                                                                */
2161 /*                                                                        */
2162 /*  CALLS                                                                 */
2163 /*                                                                        */
2164 /*    nx_packet_allocate                    Allocate a packet             */
2165 /*    nxd_udp_socket_source_send            Send a UDP packet             */
2166 /*    nx_packet_release                     Release a packet              */
2167 /*                                                                        */
2168 /*  CALLED BY                                                             */
2169 /*                                                                        */
2170 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
2171 /*    _nx_ptp_client_process_event_packet   Process PTP event packet      */
2172 /*                                                                        */
2173 /*  RELEASE HISTORY                                                       */
2174 /*                                                                        */
2175 /*    DATE              NAME                      DESCRIPTION             */
2176 /*                                                                        */
2177 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
2178 /*                                                                        */
2179 /**************************************************************************/
_nx_ptp_client_send_pdelay_resp(NX_PTP_CLIENT * client_ptr)2180 static VOID _nx_ptp_client_send_pdelay_resp(NX_PTP_CLIENT *client_ptr)
2181 {
2182 NX_PACKET *packet_ptr;
2183 UINT       status = NX_NOT_SUCCESSFUL;
2184 UCHAR     *ptr;
2185 #if NX_PTP_CLIENT_TRANSPORT_UDP
2186 NXD_ADDRESS       addr;
2187 UINT              addr_index = 0;
2188 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2189 NXD_IPV6_ADDRESS *ipv6_addr;
2190 NX_IP            *ip_ptr;
2191 NX_INTERFACE     *if_ptr;
2192 #endif
2193 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2194 
2195     /* Verify state */
2196     if (client_ptr -> nx_ptp_client_pdelay_responder_state != NX_PTP_CLIENT_PDELAY_SEND_RESP_TWOSTEP)
2197     {
2198         return;
2199     }
2200 
2201     /* Allocate a packet from the pool */
2202     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
2203     if (status != NX_SUCCESS)
2204     {
2205         /* Failed to allocate the packet */
2206         return;
2207     }
2208 
2209     /* Start of message */
2210     ptr = packet_ptr -> nx_packet_prepend_ptr;
2211 
2212 #define PTP_MSG_PDELAY_RESP_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN + NX_PTP_MSG_PDELAY_RESERVED_LEN)
2213 
2214     /* Write header IEEE Std 1588-2008 Section 13.3.1*/
2215     /* messageType */
2216     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_PDELAY_RESP;
2217     /* versionPTP */
2218     *ptr++ = NX_PTP_VERSION;
2219     /* messageLength */
2220     *ptr++ = PTP_MSG_PDELAY_REQ_TOTAL_LEN >> 8;
2221     *ptr++ = (UCHAR)PTP_MSG_PDELAY_REQ_TOTAL_LEN;
2222     /* domainNumber */
2223     *ptr++ = client_ptr -> nx_ptp_client_domain;
2224     /* reserved 1 octets */
2225     *ptr++ = 0;
2226     /* flags 2 octets */
2227     *ptr++ = 0x02;
2228     *ptr++ = 0x8;
2229     /* correction + reserved 8 + 4 */
2230     memset(ptr, 0, 12);
2231     ptr += 12;
2232     /* sourcePortIdentity */
2233     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2234     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2235     /* sequenceID */
2236     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_responder_id >> 8);
2237     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_pdelay_responder_id);
2238     /* control */
2239     *ptr++ = 5; /* other message */
2240     /* XXX */
2241     *ptr++ = 0;
2242 
2243     /* write timestamp t2 */
2244     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_pdelay_req_receipt).second_high >> 8);
2245     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_pdelay_req_receipt).second_high);
2246     /* 4 octets for second low */
2247     _nx_ptp_utility_32_unsigned_write(ptr, (client_ptr -> nx_ptp_client_pdelay_req_receipt).second_low);
2248     ptr += 4;
2249     /* 4 for nanosecond */
2250     _nx_ptp_utility_32_unsigned_write(ptr, (ULONG)(client_ptr -> nx_ptp_client_pdelay_req_receipt.nanosecond));
2251     ptr += 4;
2252 
2253     /* write requestingPortIdentity */
2254     memcpy(ptr, client_ptr -> nx_ptp_client_request_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2255     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2256 
2257     /* set final message length */
2258     packet_ptr -> nx_packet_length = (ULONG)(ptr - (packet_ptr -> nx_packet_prepend_ptr));
2259     packet_ptr -> nx_packet_append_ptr = ptr;
2260 
2261 #if NX_PTP_CLIENT_TRANSPORT_UDP
2262     /* set source and destination addresses */
2263 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2264     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
2265     {
2266         NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(&addr);
2267 
2268         /* Use first IPv6 address as source address. */
2269         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
2270         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
2271         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
2272         if (ipv6_addr == NX_NULL)
2273         {
2274 
2275             /* No available IPv6 address.  */
2276             /* Release packet.  */
2277             nx_packet_release(packet_ptr);
2278 
2279             /* Reset state.  */
2280             client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
2281             client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
2282 
2283             return;
2284         }
2285         addr_index = ipv6_addr -> nxd_ipv6_address_index;
2286     }
2287     else
2288 #endif
2289     {
2290 #ifndef NX_DISABLE_IPV4
2291         addr.nxd_ip_version = NX_IP_VERSION_V4;
2292         addr.nxd_ip_address.v4 = NX_PTP_IPV4_P2P_MULTICAST_ADDR;
2293         addr_index = client_ptr -> nx_ptp_client_interface_index;
2294 #endif
2295     }
2296 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2297 
2298     client_ptr -> nx_ptp_client_pdelay_resp_packet_ptr = packet_ptr;
2299 
2300      /* Prepare timestamp for current packet (generate t3) */
2301     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
2302                                                &client_ptr -> nx_ptp_client_pdelay_resp_origin, packet_ptr,
2303                                                client_ptr -> nx_ptp_client_clock_callback_data);
2304 
2305 
2306 #if NX_PTP_CLIENT_TRANSPORT_UDP
2307     /* Send Pdelay_Resp */
2308     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
2309                                         packet_ptr, &addr, NX_PTP_GENERAL_UDP_PORT, addr_index);
2310 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2311 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
2312     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
2313                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
2314                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
2315                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
2316                                  NX_PTP_ETHERNET_TYPE);
2317 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
2318     if (status)
2319     {
2320         /* release packet in case of error */
2321         nx_packet_release(packet_ptr);
2322 
2323         /* reset state */
2324         client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_WAIT_REQ;
2325         client_ptr -> nx_ptp_client_pdelay_req_packet_ptr = NX_NULL;
2326 
2327         return;
2328     }
2329 }
2330 #endif /* NX_ENABLE_GPTP*/
2331 
2332 
2333 #if defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
2334 /**************************************************************************/
2335 /*                                                                        */
2336 /*  FUNCTION                                               RELEASE        */
2337 /*                                                                        */
2338 /*    _nx_ptp_client_send_follow_up                       PORTABLE C      */
2339 /*                                                           6.4.0        */
2340 /*  AUTHOR                                                                */
2341 /*                                                                        */
2342 /*    Tiejun Zhou, Microsoft Corporation                                  */
2343 /*                                                                        */
2344 /*  DESCRIPTION                                                           */
2345 /*                                                                        */
2346 /*    This function sends a PTP follow up message.                        */
2347 /*                                                                        */
2348 /*  INPUT                                                                 */
2349 /*                                                                        */
2350 /*    client_ptr                            Pointer to PTP client         */
2351 /*                                                                        */
2352 /*  OUTPUT                                                                */
2353 /*                                                                        */
2354 /*    None                                                                */
2355 /*                                                                        */
2356 /*  CALLS                                                                 */
2357 /*                                                                        */
2358 /*    nx_packet_allocate                    Allocate a packet             */
2359 /*    nxd_udp_socket_source_send            Send a UDP packet             */
2360 /*    nx_packet_release                     Release a packet              */
2361 /*                                                                        */
2362 /*  CALLED BY                                                             */
2363 /*                                                                        */
2364 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
2365 /*                                                                        */
2366 /*  RELEASE HISTORY                                                       */
2367 /*                                                                        */
2368 /*    DATE              NAME                      DESCRIPTION             */
2369 /*                                                                        */
2370 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
2371 /*                                                                        */
2372 /**************************************************************************/
_nx_ptp_client_send_follow_up(NX_PTP_CLIENT * client_ptr)2373 static VOID _nx_ptp_client_send_follow_up(NX_PTP_CLIENT *client_ptr)
2374 {
2375 NX_PACKET *packet_ptr;
2376 UINT       status = NX_NOT_SUCCESSFUL;
2377 UCHAR     *ptr;
2378 #if NX_PTP_CLIENT_TRANSPORT_UDP
2379 NXD_ADDRESS       addr;
2380 UINT              addr_index = 0;
2381 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2382 NXD_IPV6_ADDRESS *ipv6_addr;
2383 NX_IP            *ip_ptr;
2384 NX_INTERFACE     *if_ptr;
2385 #endif
2386 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2387 
2388     /* allocate a packet from the pool */
2389     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
2390     if (status != NX_SUCCESS)
2391     {
2392         /* Failed to allocate the packet */
2393         return;
2394     }
2395 
2396     /* start of message */
2397     ptr = packet_ptr -> nx_packet_prepend_ptr;
2398 
2399 #define PTP_FOLLOW_UP_TLV_LENGTH    32
2400 #define PTP_MSG_FOLLOW_UP_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN + PTP_FOLLOW_UP_TLV_LENGTH)
2401 
2402     /* write header */
2403     /* messageType */
2404     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_FOLLOW_UP;
2405     /* versionPTP */
2406     *ptr++ = NX_PTP_VERSION;
2407     /* messageLength */
2408     *ptr++ = PTP_MSG_FOLLOW_UP_TOTAL_LEN >> 8;
2409     *ptr++ = (UCHAR)PTP_MSG_FOLLOW_UP_TOTAL_LEN;
2410     /* domainNumber */
2411     *ptr++ = client_ptr -> nx_ptp_client_domain;
2412     /* reserved 1 octets */
2413     *ptr++ = 0;
2414     /* flags 2 octets */
2415     *ptr++ = 0;
2416     *ptr++ = 0x08;
2417     /* correction + reserved 8 + 4 */
2418     memset(ptr, 0, 12);
2419     ptr += 12;
2420     /* sourcePortIdentity */
2421     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2422     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2423     /* sequenceID */
2424     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId >> 8);
2425     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId);
2426     /* control */
2427     *ptr++ = 2; /* follow up message */
2428     /* XXX */
2429     *ptr++ = 0;
2430 
2431     /* write preciseOriginTimestamp */
2432     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_sync_ts_local).second_high >> 8);
2433     *ptr++ = (UCHAR)((client_ptr -> nx_ptp_client_sync_ts_local).second_high);
2434     /* 4 octets for second low */
2435     _nx_ptp_utility_32_unsigned_write(ptr, (client_ptr -> nx_ptp_client_sync_ts_local).second_low);
2436     ptr += 4;
2437     /* 4 for nanosecond */
2438     _nx_ptp_utility_32_unsigned_write(ptr, (ULONG)(client_ptr -> nx_ptp_client_sync_ts_local.nanosecond));
2439     ptr += 4;
2440 
2441     /* Follow_Up information TLV definition 801AS-2020 11.4.4.3. Required by 801AS-2020 Section 7.5 g) */
2442     /* tlvType */
2443     *ptr++ = 0;
2444     *ptr++ = 0x3;
2445     /* lengthField */
2446     *ptr++ = 0;
2447     *ptr++ = 28;
2448     /* organizationId(3): 00-80-C2 from 801AS-2020 11.4.4.3.4 */
2449     *ptr++ = 0x0;
2450     *ptr++ = 0x80;
2451     *ptr++ = 0xC2;
2452     /* organizationSubType(3): 1 */
2453     *ptr++ = 0x0;
2454     *ptr++ = 0x0;
2455     *ptr++ = 0x1;
2456     /* cumulativeScaledRateOffset(4) */
2457     /* gmTimeBaseIndicator(2) */
2458     /* lastGmPhaseChange(12) */
2459     /* scaledLastGmFreqChange(4) */
2460 #define PTP_FOLLOW_UP_TLV_ZEROES 4 + 2 + 12 + 4
2461     memset(ptr, 0, PTP_FOLLOW_UP_TLV_ZEROES);
2462     ptr += PTP_FOLLOW_UP_TLV_ZEROES;
2463 
2464     /* set final length of message */
2465     packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr);
2466     packet_ptr -> nx_packet_append_ptr = ptr;
2467 
2468 #if NX_PTP_CLIENT_TRANSPORT_UDP
2469     /* set source and destination addresses */
2470 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2471     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
2472     {
2473         NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
2474 
2475         /* Use first IPv6 address as source address. */
2476         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
2477         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
2478         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
2479         if (ipv6_addr == NX_NULL)
2480         {
2481 
2482             /* No available IPv6 address.  */
2483             /* Release packet.  */
2484             nx_packet_release(packet_ptr);
2485 
2486             /* Reset state.  */
2487             client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
2488 
2489             return;
2490         }
2491         addr_index = ipv6_addr -> nxd_ipv6_address_index;
2492     }
2493     else
2494 #endif
2495     {
2496 #ifndef NX_DISABLE_IPV4
2497         addr.nxd_ip_version = NX_IP_VERSION_V4;
2498         addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
2499         addr_index = client_ptr -> nx_ptp_client_interface_index;
2500 #endif
2501     }
2502 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2503 
2504 #if NX_PTP_CLIENT_TRANSPORT_UDP
2505     /* Send Pdelay_Resp */
2506     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
2507                                         packet_ptr, &addr, NX_PTP_GENERAL_UDP_PORT, addr_index);
2508 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2509 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
2510     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
2511                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
2512                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
2513                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
2514                                  NX_PTP_ETHERNET_TYPE);
2515 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
2516 
2517     if (status)
2518     {
2519 
2520         /* release packet in case of error */
2521         nx_packet_release(packet_ptr);
2522     }
2523 }
2524 
2525 
2526 /**************************************************************************/
2527 /*                                                                        */
2528 /*  FUNCTION                                               RELEASE        */
2529 /*                                                                        */
2530 /*    _nx_ptp_client_send_sync                            PORTABLE C      */
2531 /*                                                           6.4.0        */
2532 /*  AUTHOR                                                                */
2533 /*                                                                        */
2534 /*    Tiejun Zhou, Microsoft Corporation                                  */
2535 /*                                                                        */
2536 /*  DESCRIPTION                                                           */
2537 /*                                                                        */
2538 /*    This function sends a PTP sync message.                             */
2539 /*                                                                        */
2540 /*  INPUT                                                                 */
2541 /*                                                                        */
2542 /*    client_ptr                            Pointer to PTP client         */
2543 /*                                                                        */
2544 /*  OUTPUT                                                                */
2545 /*                                                                        */
2546 /*    None                                                                */
2547 /*                                                                        */
2548 /*  CALLS                                                                 */
2549 /*                                                                        */
2550 /*    nx_packet_allocate                    Allocate a packet             */
2551 /*    nxd_udp_socket_source_send            Send a UDP packet             */
2552 /*    nx_packet_release                     Release a packet              */
2553 /*                                                                        */
2554 /*  CALLED BY                                                             */
2555 /*                                                                        */
2556 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
2557 /*                                                                        */
2558 /*  RELEASE HISTORY                                                       */
2559 /*                                                                        */
2560 /*    DATE              NAME                      DESCRIPTION             */
2561 /*                                                                        */
2562 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
2563 /*                                                                        */
2564 /**************************************************************************/
_nx_ptp_client_send_sync(NX_PTP_CLIENT * client_ptr)2565 static VOID _nx_ptp_client_send_sync(NX_PTP_CLIENT *client_ptr)
2566 {
2567 NX_PACKET *packet_ptr;
2568 UINT       status = NX_NOT_SUCCESSFUL;
2569 UCHAR     *ptr;
2570 #if NX_PTP_CLIENT_TRANSPORT_UDP
2571 NXD_ADDRESS       addr;
2572 UINT              addr_index = 0;
2573 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2574 NXD_IPV6_ADDRESS *ipv6_addr;
2575 NX_IP            *ip_ptr;
2576 NX_INTERFACE     *if_ptr;
2577 #endif
2578 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2579 
2580     /* allocate a packet from the pool */
2581     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
2582     if (status != NX_SUCCESS)
2583     {
2584         /* Failed to allocate the packet */
2585         return;
2586     }
2587 
2588     /* start of message */
2589     ptr = packet_ptr -> nx_packet_prepend_ptr;
2590 
2591 #define PTP_MSG_SYNC_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN)
2592 
2593     /* write header */
2594     /* messageType */
2595     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_SYNC;
2596     /* versionPTP */
2597     *ptr++ = NX_PTP_VERSION;
2598     /* messageLength */
2599     *ptr++ = PTP_MSG_SYNC_TOTAL_LEN >> 8;
2600     *ptr++ = (UCHAR)PTP_MSG_SYNC_TOTAL_LEN;
2601     /* domainNumber */
2602     *ptr++ = client_ptr -> nx_ptp_client_domain;
2603     /* reserved 1 octets */
2604     *ptr++ = 0;
2605     /* flags 2 octets */
2606     *ptr++ = 0x02;
2607     *ptr++ = 0x08;
2608     /* correction + reserved 8 + 4 */
2609     memset(ptr, 0, 12);
2610     ptr += 12;
2611     /* sourcePortIdentity */
2612     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2613     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2614     /* sequenceID */
2615     client_ptr -> nx_ptp_client_sync_sequenceId++;
2616     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId >> 8);
2617     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId);
2618     /* control */
2619     *ptr++ = 0; /* sync message */
2620     /* XXX */
2621     *ptr++ = (UCHAR)(NX_PTP_CLIENT_LOG_SYNC_INTERVAL);
2622 
2623     /* write timestamp (0) */
2624     memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
2625     ptr += NX_PTP_MSG_TIMESTAMP_LEN;
2626 
2627     /* set final length of message */
2628     packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr);
2629     packet_ptr -> nx_packet_append_ptr = ptr;
2630 
2631     #if NX_PTP_CLIENT_TRANSPORT_UDP
2632     /* set source and destination addresses */
2633 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2634     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
2635     {
2636         NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
2637 
2638         /* Use first IPv6 address as source address. */
2639         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
2640         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
2641         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
2642         if (ipv6_addr == NX_NULL)
2643         {
2644 
2645             /* No available IPv6 address.  */
2646             /* Release packet.  */
2647             nx_packet_release(packet_ptr);
2648 
2649             return;
2650         }
2651         addr_index = ipv6_addr -> nxd_ipv6_address_index;
2652     }
2653     else
2654 #endif
2655     {
2656 #ifndef NX_DISABLE_IPV4
2657         addr.nxd_ip_version = NX_IP_VERSION_V4;
2658         addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
2659         addr_index = client_ptr -> nx_ptp_client_interface_index;
2660 #endif
2661     }
2662 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2663 
2664     /* Prepare timestamp for current packet  */
2665     client_ptr -> nx_ptp_client_sync_packet_ptr = packet_ptr;
2666     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
2667                                                &client_ptr -> nx_ptp_client_sync_ts_local, packet_ptr,
2668                                                client_ptr -> nx_ptp_client_clock_callback_data);
2669 
2670 #if NX_PTP_CLIENT_TRANSPORT_UDP
2671     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
2672                                         packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index);
2673 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2674 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
2675     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
2676                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
2677                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
2678                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
2679                                  NX_PTP_ETHERNET_TYPE);
2680 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
2681 
2682     if (status)
2683     {
2684 
2685         /* release packet in case of error */
2686         nx_packet_release(packet_ptr);
2687     }
2688 }
2689 #endif /* defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC) */
2690 
2691 
2692 #ifdef NX_PTP_ENABLE_MASTER
2693 /**************************************************************************/
2694 /*                                                                        */
2695 /*  FUNCTION                                               RELEASE        */
2696 /*                                                                        */
2697 /*    _nx_ptp_client_send_announce                        PORTABLE C      */
2698 /*                                                           6.4.0        */
2699 /*  AUTHOR                                                                */
2700 /*                                                                        */
2701 /*    Tiejun Zhou, Microsoft Corporation                                  */
2702 /*                                                                        */
2703 /*  DESCRIPTION                                                           */
2704 /*                                                                        */
2705 /*    This function sends a PTP announce message.                         */
2706 /*                                                                        */
2707 /*  INPUT                                                                 */
2708 /*                                                                        */
2709 /*    client_ptr                            Pointer to PTP client         */
2710 /*                                                                        */
2711 /*  OUTPUT                                                                */
2712 /*                                                                        */
2713 /*    None                                                                */
2714 /*                                                                        */
2715 /*  CALLS                                                                 */
2716 /*                                                                        */
2717 /*    nx_packet_allocate                    Allocate a packet             */
2718 /*    nxd_udp_socket_source_send            Send a UDP packet             */
2719 /*    nx_packet_release                     Release a packet              */
2720 /*                                                                        */
2721 /*  CALLED BY                                                             */
2722 /*                                                                        */
2723 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
2724 /*                                                                        */
2725 /*  RELEASE HISTORY                                                       */
2726 /*                                                                        */
2727 /*    DATE              NAME                      DESCRIPTION             */
2728 /*                                                                        */
2729 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
2730 /*                                                                        */
2731 /**************************************************************************/
_nx_ptp_client_send_announce(NX_PTP_CLIENT * client_ptr)2732 static VOID _nx_ptp_client_send_announce(NX_PTP_CLIENT *client_ptr)
2733 {
2734 NX_PACKET *packet_ptr;
2735 UINT       status = NX_NOT_SUCCESSFUL;
2736 UCHAR     *ptr;
2737 #if NX_PTP_CLIENT_TRANSPORT_UDP
2738 NXD_ADDRESS       addr;
2739 UINT              addr_index = 0;
2740 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2741 NXD_IPV6_ADDRESS *ipv6_addr;
2742 NX_IP            *ip_ptr;
2743 NX_INTERFACE     *if_ptr;
2744 #endif
2745 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2746 
2747     /* Verify state */
2748 
2749     /* Allocate a packet from the pool */
2750     status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_PTP_PACKET, NX_NO_WAIT);
2751     if (status != NX_SUCCESS)
2752     {
2753         /* Failed to allocate the packet */
2754         return;
2755     }
2756 
2757     /* Start of message */
2758     ptr = packet_ptr -> nx_packet_prepend_ptr;
2759 
2760 #define PTP_MSG_ANNOUNCE_PATH_TLV_LEN (2 + 2 + NX_PTP_CLOCK_IDENTITY_SIZE)
2761 #define PTP_MSG_ANNOUNCE_TOTAL_LEN    (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_ANNOUNCE_LEN + PTP_MSG_ANNOUNCE_PATH_TLV_LEN)
2762 
2763     /* Write header IEEE Std 1588-2008 Section 13.3.1*/
2764     /* messageType */
2765     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | NX_PTP_MSG_TYPE_ANNOUNCE;
2766     /* versionPTP */
2767     *ptr++ = NX_PTP_VERSION;
2768     /* messageLength */
2769     *ptr++ = PTP_MSG_ANNOUNCE_TOTAL_LEN >> 8;
2770     *ptr++ = (UCHAR)PTP_MSG_ANNOUNCE_TOTAL_LEN;
2771     /* domainNumber */
2772     *ptr++ = client_ptr -> nx_ptp_client_domain;
2773     /* reserved 1 octets */
2774     *ptr++ = 0;
2775     /* flags 2 octets */
2776     *ptr++ = 0;
2777     *ptr++ = 0x08;
2778     /* correction + reserved 8 + 4 */
2779     memset(ptr, 0, 12);
2780     ptr += 12;
2781     /* sourcePortIdentity */
2782     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2783     ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2784     /* sequenceID */
2785     client_ptr -> nx_ptp_client_sync_sequenceId++;
2786     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId >> 8);
2787     *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_sync_sequenceId);
2788     /* control */
2789     *ptr++ = 5; /* other message */
2790     /* XXX */ /* 13.3.2.14 logMessageInterval */
2791     *ptr++ = 0x0;
2792 
2793     /* Write announce message field IEEE Std 1588-2019 Section 13.5.2 */
2794     /* write originTimestamp */
2795     memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
2796     ptr += NX_PTP_MSG_TIMESTAMP_LEN;
2797     /* currentUtcOffset */
2798     *ptr++ = 0;
2799     *ptr++ = 0;
2800     /* reserved */
2801     *ptr++ = 0;
2802     /* grandmasterPriority1 */
2803     *ptr++ = (client_ptr -> ptp_master).nx_ptp_client_master_priority1;
2804     /* grandmasterClockQuality(4) = grandmasterClockClass(1) + grandmasterClockAccuracy(1) + grandmasterClockVariance(2) */
2805     *ptr++ = (client_ptr -> ptp_master).nx_ptp_client_master_clock_class;
2806     *ptr++ = (client_ptr -> ptp_master).nx_ptp_client_master_clock_accuracy;
2807     *ptr++ = (UCHAR)((client_ptr -> ptp_master).nx_ptp_client_master_offset_scaled_log_variance >> 8);
2808     *ptr++ = (UCHAR)((client_ptr -> ptp_master).nx_ptp_client_master_offset_scaled_log_variance);
2809     /* grandmasterPriority2 */
2810     *ptr++ = (client_ptr -> ptp_master).nx_ptp_client_master_priority2;
2811     /* grandmasterIdentity. Setting to client_port_identity because grandmaster */
2812     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_IDENTITY_SIZE); /* use case of memcpy is verified. */
2813     ptr += NX_PTP_CLOCK_IDENTITY_SIZE;
2814     /* stepsRemoved */
2815     *ptr++ = 0;
2816     *ptr++ = 0;
2817     /* timeSource */
2818     *ptr++ = (client_ptr -> ptp_master).nx_ptp_client_master_time_source;
2819 
2820     /* Path trace TLV */
2821     /* tlvType */
2822     *ptr++ = 0;
2823     *ptr++ = 0x8;
2824     /* lengthField */
2825     *ptr++ = 0;
2826     *ptr++ = 0x8;
2827     /* pathSequence */
2828     memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, NX_PTP_CLOCK_IDENTITY_SIZE); /* use case of memcpy is verified. */
2829     ptr += NX_PTP_CLOCK_IDENTITY_SIZE;
2830 
2831     /* set final message length */
2832     packet_ptr -> nx_packet_length = (ULONG)(ptr - (packet_ptr -> nx_packet_prepend_ptr));
2833     packet_ptr -> nx_packet_append_ptr = ptr;
2834 
2835 #if NX_PTP_CLIENT_TRANSPORT_UDP
2836     /* set source and destination addresses */
2837 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2838     if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
2839     {
2840         NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
2841 
2842         /* Use first IPv6 address as source address. */
2843         ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
2844         if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
2845         ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
2846         if (ipv6_addr == NX_NULL)
2847         {
2848 
2849             /* No available IPv6 address.  */
2850             /* Release packet.  */
2851             nx_packet_release(packet_ptr);
2852 
2853             return;
2854         }
2855         addr_index = ipv6_addr -> nxd_ipv6_address_index;
2856     }
2857     else
2858 #endif
2859     {
2860 #ifndef NX_DISABLE_IPV4
2861         addr.nxd_ip_version = NX_IP_VERSION_V4;
2862         addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
2863         addr_index = client_ptr -> nx_ptp_client_interface_index;
2864 #endif
2865     }
2866 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2867 
2868 #if NX_PTP_CLIENT_TRANSPORT_UDP
2869     status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
2870                                         packet_ptr, &addr, NX_PTP_GENERAL_UDP_PORT, addr_index);
2871 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
2872 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
2873     nx_link_ethernet_packet_send(client_ptr -> nx_ptp_client_ip_ptr,
2874                                  client_ptr -> nx_ptp_client_interface_index, packet_ptr,
2875                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
2876                                  NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB,
2877                                  NX_PTP_ETHERNET_TYPE);
2878 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
2879     if (status)
2880     {
2881         /* release packet in case of error */
2882         nx_packet_release(packet_ptr);
2883     }
2884 }
2885 #endif /* NX_PTP_ENABLE_MASTER */
2886 
2887 /**************************************************************************/
2888 /*                                                                        */
2889 /*  FUNCTION                                               RELEASE        */
2890 /*                                                                        */
2891 /*    _nx_ptp_client_process_event_packet                 PORTABLE C      */
2892 /*                                                           6.4.0        */
2893 /*  AUTHOR                                                                */
2894 /*                                                                        */
2895 /*    Yuxin Zhou, Microsoft Corporation                                   */
2896 /*                                                                        */
2897 /*  DESCRIPTION                                                           */
2898 /*                                                                        */
2899 /*    This function processes PTP packet received through event socket.   */
2900 /*                                                                        */
2901 /*  INPUT                                                                 */
2902 /*                                                                        */
2903 /*    client_ptr                            Pointer to PTP client         */
2904 /*    packet_ptr                            Pointer to PTP packet         */
2905 /*    hdr                                   Pointer to PTP header         */
2906 /*                                                                        */
2907 /*  OUTPUT                                                                */
2908 /*                                                                        */
2909 /*    None                                                                */
2910 /*                                                                        */
2911 /*  CALLS                                                                 */
2912 /*                                                                        */
2913 /*    _nx_ptp_client_sync_received          Process Sync message          */
2914 /*    _nx_ptp_msg_parse_hdr                 Parse PTP header              */
2915 /*    memcmp                                Compare memory                */
2916 /*                                                                        */
2917 /*  CALLED BY                                                             */
2918 /*                                                                        */
2919 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
2920 /*    _nx_ptp_client_send_pdelay_resp       Send pdelay response          */
2921 /*                                                                        */
2922 /*  RELEASE HISTORY                                                       */
2923 /*                                                                        */
2924 /*    DATE              NAME                      DESCRIPTION             */
2925 /*                                                                        */
2926 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
2927 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
2928 /*                                            supported gPTP profile,     */
2929 /*                                            supported master clock,     */
2930 /*                                            resulting in version 6.4.0  */
2931 /*                                                                        */
2932 /**************************************************************************/
_nx_ptp_client_process_event_packet(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_PTP_MSG_HEADER * hdr)2933 static VOID _nx_ptp_client_process_event_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr,
2934                                                 NX_PTP_MSG_HEADER *hdr)
2935 {
2936 
2937 #if defined(NX_ENABLE_GPTP)
2938     if (hdr -> messageType == NX_PTP_MSG_TYPE_PDELAY_REQ)
2939     {
2940 
2941         if (packet_ptr -> nx_packet_length < NX_PTP_MSG_PDELAY_REQ_LEN)
2942         {
2943             /* not waiting for Pdelay_Req or invalid message */
2944             return;
2945         }
2946 
2947         /* record timestamp of received message (t2) */
2948         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_TS_EXTRACT_ETHERNET,
2949                                                 &client_ptr -> nx_ptp_client_pdelay_req_receipt, packet_ptr,
2950                                                 client_ptr -> nx_ptp_client_clock_callback_data);
2951 
2952         /* update request_id */
2953         client_ptr -> nx_ptp_client_pdelay_responder_id = hdr -> sequenceId;
2954 
2955         /* update nx_ptp_client_request_port_identity */
2956         memcpy(client_ptr -> nx_ptp_client_request_port_identity, hdr -> sourcePortIdentity,
2957                NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2958 
2959         client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_SEND_RESP_TWOSTEP;
2960         _nx_ptp_client_send_pdelay_resp(client_ptr);
2961     }
2962     else if (hdr -> messageType == NX_PTP_MSG_TYPE_PDELAY_RESP)
2963     {
2964         if ((client_ptr -> nx_ptp_client_pdelay_initiator_state != NX_PTP_CLIENT_PDELAY_WAIT_RESP) ||
2965             (client_ptr -> nx_ptp_client_pdelay_req_id != hdr -> sequenceId) ||
2966             (packet_ptr -> nx_packet_length < NX_PTP_MSG_PDELAY_RESP_LEN))
2967         {
2968 
2969             /* not waiting for Pdelay_resp or invalid message */
2970             return;
2971         }
2972 
2973         /* retrieve timestamp of event message */
2974         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_TS_EXTRACT_ETHERNET,
2975                                                 &client_ptr -> nx_ptp_client_pdelay_resp_ts, packet_ptr,
2976                                                 client_ptr -> nx_ptp_client_clock_callback_data);
2977 
2978         /* get t2 timestamp */
2979         _nx_ptp_msg_parse_timestamp(packet_ptr -> nx_packet_prepend_ptr, &client_ptr -> nx_ptp_client_pdelay_req_receipt_ts);
2980 
2981         /* two-step message? */
2982         if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP)
2983         {
2984             client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_WAIT_RESP_FOLLOW_UP;
2985         }
2986         else
2987         {
2988             /* process Pdelay_Resp event */
2989             _nx_ptp_client_pdelay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
2990         }
2991     }
2992 #endif
2993 
2994     if (hdr -> messageType == NX_PTP_MSG_TYPE_SYNC)
2995     {
2996         if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_SLAVE) ||
2997             (packet_ptr -> nx_packet_length < NX_PTP_MSG_SYNC_LEN))
2998         {
2999 
3000             /* not waiting for Sync or invalid message */
3001             return;
3002         }
3003 
3004         /* Store previous sync timestamp.  */
3005         NX_PTP_TS_COPY(client_ptr -> nx_ptp_client_prev_sync, client_ptr -> nx_ptp_client_sync);
3006         NX_PTP_TS_COPY(client_ptr -> nx_ptp_client_prev_sync_ts, client_ptr -> nx_ptp_client_sync_ts);
3007 
3008         /* retrieve timestamp of event message */
3009         client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT,
3010                                                 &client_ptr -> nx_ptp_client_sync_ts, packet_ptr,
3011                                                 client_ptr -> nx_ptp_client_clock_callback_data);
3012 
3013         /* two-step message? */
3014         if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP)
3015         {
3016 
3017             /* wait for follow up message */
3018             client_ptr -> nx_ptp_client_sync_id = hdr -> sequenceId;
3019         }
3020         else
3021         {
3022 
3023             /* process Sync event */
3024             _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr, hdr);
3025         }
3026     }
3027 }
3028 
3029 
3030 /**************************************************************************/
3031 /*                                                                        */
3032 /*  FUNCTION                                               RELEASE        */
3033 /*                                                                        */
3034 /*    _nx_ptp_client_process_general_packet               PORTABLE C      */
3035 /*                                                           6.4.0        */
3036 /*  AUTHOR                                                                */
3037 /*                                                                        */
3038 /*    Yuxin Zhou, Microsoft Corporation                                   */
3039 /*                                                                        */
3040 /*  DESCRIPTION                                                           */
3041 /*                                                                        */
3042 /*    This function processes PTP packet received through general socket. */
3043 /*                                                                        */
3044 /*  INPUT                                                                 */
3045 /*                                                                        */
3046 /*    client_ptr                            Pointer to PTP client         */
3047 /*    packet_ptr                            Pointer to PTP packet         */
3048 /*    hdr                                   Pointer to PTP header         */
3049 /*                                                                        */
3050 /*  OUTPUT                                                                */
3051 /*                                                                        */
3052 /*    None                                                                */
3053 /*                                                                        */
3054 /*  CALLS                                                                 */
3055 /*                                                                        */
3056 /*    _nx_ptp_client_sync_received          Process Sync message          */
3057 /*    _nx_ptp_msg_parse_hdr                 Parse PTP header              */
3058 /*    _nx_ptp_client_delay_resp_received    Process delay response        */
3059 /*    _nx_ptp_client_init_packet_received   Process Announce message      */
3060 /*    memcmp                                Compare memory                */
3061 /*                                                                        */
3062 /*  CALLED BY                                                             */
3063 /*                                                                        */
3064 /*    _nx_ptp_client_thread_entry           PTP thread entry              */
3065 /*                                                                        */
3066 /*  RELEASE HISTORY                                                       */
3067 /*                                                                        */
3068 /*    DATE              NAME                      DESCRIPTION             */
3069 /*                                                                        */
3070 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3071 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
3072 /*                                            supported gPTP profile,     */
3073 /*                                            supported master clock,     */
3074 /*                                            resulting in version 6.4.0  */
3075 /*                                                                        */
3076 /**************************************************************************/
_nx_ptp_client_process_general_packet(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_PTP_MSG_HEADER * hdr)3077 static VOID _nx_ptp_client_process_general_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr,
3078                                                   NX_PTP_MSG_HEADER *hdr)
3079 {
3080 
3081     /* process ANNOUNCE message */
3082     if (hdr -> messageType == NX_PTP_MSG_TYPE_ANNOUNCE)
3083     {
3084         if (packet_ptr -> nx_packet_length < NX_PTP_MSG_ANNOUNCE_LEN)
3085         {
3086 
3087             /* invalid message */
3088             return;
3089         }
3090 
3091         /* process announce message */
3092         _nx_ptp_client_init_packet_received(client_ptr, hdr, packet_ptr -> nx_packet_prepend_ptr);
3093     }
3094     /* process FOLLOW_UP message */
3095     else if (hdr -> messageType == NX_PTP_MSG_TYPE_FOLLOW_UP)
3096     {
3097         if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_SLAVE) ||
3098             (client_ptr -> nx_ptp_client_sync_id != hdr -> sequenceId) ||
3099             (packet_ptr -> nx_packet_length < NX_PTP_MSG_FOLLOW_UP_LEN))
3100         {
3101 
3102             /* not a follow up for a previous Sync or invalid message */
3103             return;
3104         }
3105 
3106         /* process Sync message */
3107         _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr, hdr);
3108     }
3109 #if defined(NX_ENABLE_GPTP)
3110     if (hdr -> messageType == NX_PTP_MSG_TYPE_PDELAY_RESP_FOLLOW_UP)
3111     {
3112         if ((client_ptr -> nx_ptp_client_pdelay_initiator_state != NX_PTP_CLIENT_PDELAY_WAIT_RESP_FOLLOW_UP) ||
3113             (client_ptr -> nx_ptp_client_pdelay_req_id != hdr -> sequenceId) ||
3114             (packet_ptr -> nx_packet_length < NX_PTP_MSG_PDELAY_RESP_FOLLOW_UP_LEN))
3115         {
3116 
3117             /* not a follow up for a previous Pdelay_resp or invalid message */
3118             return;
3119         }
3120 
3121         /* process Pdelay_Resp event */
3122         _nx_ptp_client_pdelay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
3123     }
3124 #else
3125     else if (hdr -> messageType == NX_PTP_MSG_TYPE_DELAY_RESP)
3126     {
3127         if ((client_ptr -> nx_ptp_client_delay_state != NX_PTP_CLIENT_DELAY_WAIT_RESP) ||
3128             (client_ptr -> nx_ptp_client_delay_req_id != hdr -> sequenceId) ||
3129             (packet_ptr -> nx_packet_length < NX_PTP_MSG_DELAY_RESP_LEN) ||
3130             (memcmp(client_ptr -> nx_ptp_client_port_identity,
3131                     packet_ptr -> nx_packet_prepend_ptr + NX_PTP_MSG_TIMESTAMP_LEN,
3132                     NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
3133         {
3134 
3135             /* not a delay_resp for a previous delay_req or invalid message */
3136             return;
3137         }
3138 
3139         /* process delay response message */
3140         _nx_ptp_client_delay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
3141     }
3142 #endif
3143 }
3144 
3145 
3146 /**************************************************************************/
3147 /*                                                                        */
3148 /*  FUNCTION                                               RELEASE        */
3149 /*                                                                        */
3150 /*    _nx_ptp_client_thread_entry                         PORTABLE C      */
3151 /*                                                           6.4.0        */
3152 /*  AUTHOR                                                                */
3153 /*                                                                        */
3154 /*    Yuxin Zhou, Microsoft Corporation                                   */
3155 /*                                                                        */
3156 /*  DESCRIPTION                                                           */
3157 /*                                                                        */
3158 /*    This function implements the PTP client processing thread.          */
3159 /*                                                                        */
3160 /*  INPUT                                                                 */
3161 /*                                                                        */
3162 /*    ptp_instance                          Pointer to PTP client         */
3163 /*                                                                        */
3164 /*  OUTPUT                                                                */
3165 /*                                                                        */
3166 /*    None                                                                */
3167 /*                                                                        */
3168 /*  CALLS                                                                 */
3169 /*                                                                        */
3170 /*    _nx_ptp_client_process_general_packet Process PTP general packet    */
3171 /*    _nx_ptp_client_process_event_packet   Process PTP event packet      */
3172 /*    _nx_ptp_client_send_pdelay_resp_follow_up                           */
3173 /*                                          Send pdelay response message  */
3174 /*    _nx_ptp_client_send_follow_up         Send follow up message        */
3175 /*    _nx_ptp_client_send_sync              Send sync message             */
3176 /*    _nx_ptp_client_send_announce          Send announce message         */
3177 /*    tx_event_flags_get                    Get PTP events                */
3178 /*    nx_udp_socket_receive                 Receive a UDP packet          */
3179 /*    nx_packet_release                     Release a packet              */
3180 /*                                                                        */
3181 /*  CALLED BY                                                             */
3182 /*                                                                        */
3183 /*    ThreadX                                                             */
3184 /*                                                                        */
3185 /*  RELEASE HISTORY                                                       */
3186 /*                                                                        */
3187 /*    DATE              NAME                      DESCRIPTION             */
3188 /*                                                                        */
3189 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3190 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
3191 /*                                            supported gPTP profile,     */
3192 /*                                            supported master clock,     */
3193 /*                                            resulting in version 6.4.0  */
3194 /*                                                                        */
3195 /**************************************************************************/
_nx_ptp_client_thread_entry(ULONG ptp_instance)3196 static VOID _nx_ptp_client_thread_entry(ULONG ptp_instance)
3197 {
3198 TX_INTERRUPT_SAVE_AREA
3199 NX_PTP_CLIENT    *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
3200 ULONG             ptp_events;
3201 UINT              status;
3202 NX_PACKET        *packet_ptr = NX_NULL;
3203 NX_PTP_MSG_HEADER hdr;
3204 
3205 #ifdef NX_PTP_ENABLE_MASTER
3206     if (client_ptr -> nx_ptp_client_role == NX_PTP_CLIENT_ROLE_MASTER_ONLY)
3207     {
3208 
3209         /* Set timer values */
3210         client_ptr -> ptp_master.nx_ptp_client_master_announce_timer = NX_PTP_CLIENT_ANNOUNCE_INTERVAL;
3211         client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
3212         client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_MASTER;
3213 
3214         client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER,
3215                                                    &client_ptr -> ptp_master,
3216                                                    client_ptr -> nx_ptp_client_event_callback_data);
3217     }
3218     else
3219     {
3220 
3221         /* Set timer values */
3222         client_ptr -> ptp_master.nx_ptp_client_master_announce_timer = -1;
3223         client_ptr -> nx_ptp_client_sync_timer = -1;
3224 #endif /* NX_PTP_ENABLE_MASTER */
3225         client_ptr -> nx_ptp_client_delay_req_timer = -1;
3226         client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION;
3227 
3228         /* start in listening state */
3229         client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
3230 #ifdef NX_PTP_ENABLE_MASTER
3231     }
3232 #endif /* NX_PTP_ENABLE_MASTER */
3233 
3234 #ifdef NX_ENABLE_GPTP
3235     client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_IDLE;
3236     client_ptr -> nx_ptp_client_pdelay_req_timer = NX_PTP_CLIENT_PDELAY_REQ_INTERVAL;
3237 #endif
3238 
3239     /* main loop */
3240     for (;;)
3241     {
3242 
3243         /* wait for message */
3244         status = tx_event_flags_get(&(client_ptr -> nx_ptp_client_events),
3245                                     NX_PTP_CLIENT_ALL_EVENTS, TX_OR_CLEAR,
3246                                     &ptp_events, TX_WAIT_FOREVER);
3247         if (status != TX_SUCCESS)
3248         {
3249 
3250             /* error while reading queue, abort thread */
3251             break;
3252         }
3253 
3254         if (ptp_events & NX_PTP_CLIENT_STOP_EVENT)
3255         {
3256 
3257             /* terminate thread */
3258             break;
3259         }
3260 
3261 #ifdef NX_ENABLE_GPTP
3262         if (ptp_events & NX_PTP_CLIENT_PDELAY_FOLLOW_EVENT)
3263         {
3264 
3265             /* update state to send_pdelay_resp_follow_up */
3266             client_ptr -> nx_ptp_client_pdelay_responder_state = NX_PTP_CLIENT_PDELAY_SEND_FOLLOW_UP;
3267 
3268             /* call send follow up */
3269             _nx_ptp_client_send_pdelay_resp_follow_up(client_ptr);
3270         }
3271 #endif
3272 
3273 #if defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
3274         if (ptp_events & NX_PTP_CLIENT_SYNC_FOLLOW_EVENT)
3275         {
3276 
3277             /* call send follow up */
3278             _nx_ptp_client_send_follow_up(client_ptr);
3279         }
3280 #endif /* defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC) */
3281 
3282         /*
3283          * PTP Message Received
3284          */
3285         if (ptp_events & NX_PTP_CLIENT_RX_EVENT)
3286         {
3287 
3288             /* Loop to receive all packets. */
3289             for (;;)
3290             {
3291 #if NX_PTP_CLIENT_TRANSPORT_UDP
3292                 if ((nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_event_socket),
3293                                            &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) ||
3294                     (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_general_socket),
3295                                            &packet_ptr, NX_NO_WAIT) == NX_SUCCESS))
3296                 {
3297 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
3298 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
3299                 if (client_ptr -> nx_ptp_client_received_packet_head)
3300                 {
3301 
3302                     /* Remove the first packet and process it!  */
3303 
3304                     /* Disable interrupts.  */
3305                     TX_DISABLE
3306 
3307                     /* Pickup the first packet.  */
3308                     packet_ptr =  client_ptr -> nx_ptp_client_received_packet_head;
3309 
3310                     /* Move the head pointer to the next packet.  */
3311                     client_ptr -> nx_ptp_client_received_packet_head =  packet_ptr -> nx_packet_queue_next;
3312 
3313                     /* Check for end of deferred processing queue.  */
3314                     if (client_ptr -> nx_ptp_client_received_packet_head == NX_NULL)
3315                     {
3316 
3317                         /* Yes, the queue is empty.  Set the tail pointer to NULL.  */
3318                        client_ptr -> nx_ptp_client_received_packet_tail =  NX_NULL;
3319                     }
3320 
3321                     /* Restore interrupts.  */
3322                     TX_RESTORE
3323 
3324 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
3325 
3326                     /* Parse header first.  */
3327                     if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr))
3328                     {
3329 
3330                         /* Release packet. */
3331                         nx_packet_release(packet_ptr);
3332                         continue;
3333                     }
3334 
3335                     /* check origin of message */
3336                     if ((client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_SLAVE) &&
3337                         (memcmp(&client_ptr -> nx_ptp_client_master_port_identity,
3338                                 hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
3339                     {
3340 
3341                         /* not from our master clock */
3342                         nx_packet_release(packet_ptr);
3343                         continue;
3344                     }
3345 
3346                     if ((hdr.messageType == NX_PTP_MSG_TYPE_SYNC)
3347 #ifdef NX_ENABLE_GPTP
3348                         || (hdr.messageType == NX_PTP_MSG_TYPE_PDELAY_REQ)
3349                         || (hdr.messageType == NX_PTP_MSG_TYPE_PDELAY_RESP)
3350 #endif /* NX_ENABLE_GPTP */
3351                        )
3352                     {
3353                         _nx_ptp_client_process_event_packet(client_ptr, packet_ptr, &hdr);
3354                     }
3355                     else
3356                     {
3357                         _nx_ptp_client_process_general_packet(client_ptr, packet_ptr, &hdr);
3358                     }
3359 
3360                     /* Release packet. */
3361                     nx_packet_release(packet_ptr);
3362                 }
3363                 else
3364                 {
3365                     break;
3366                 }
3367             }
3368         }
3369 
3370         /*
3371          * Timer Event
3372          */
3373         if (ptp_events & NX_PTP_CLIENT_TIMER_EVENT)
3374         {
3375 #ifdef NX_ENABLE_GPTP
3376             /* pdelay_req interval timer */
3377             if ((client_ptr -> nx_ptp_client_pdelay_req_timer > 0) &&
3378                 (--client_ptr -> nx_ptp_client_pdelay_req_timer == 0))
3379             {
3380                 _nx_ptp_client_send_pdelay_req(client_ptr);
3381             }
3382 #endif
3383 #if defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
3384 #ifdef NX_PTP_ENABLE_MASTER
3385             /* announce messages timeout */
3386             if (((client_ptr -> ptp_master).nx_ptp_client_master_announce_timer > 0) &&
3387                 (--(client_ptr -> ptp_master).nx_ptp_client_master_announce_timer == 0))
3388             {
3389                 _nx_ptp_client_send_announce(client_ptr);
3390 
3391                 /* Reset timer.  */
3392                 (client_ptr -> ptp_master).nx_ptp_client_master_announce_timer = NX_PTP_CLIENT_ANNOUNCE_INTERVAL;
3393             }
3394 #endif /* NX_PTP_ENABLE_MASTER */
3395             /* Sync messages timeout */
3396             if ((client_ptr -> nx_ptp_client_sync_timer > 0) &&
3397                 (--client_ptr -> nx_ptp_client_sync_timer == 0))
3398             {
3399                 _nx_ptp_client_send_sync(client_ptr);
3400 
3401                 /* Reset timer.  */
3402                 client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
3403             }
3404 #endif /* defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC) */
3405 
3406 #ifndef NX_PTP_DISABLE_SLAVE
3407             /* announce messages timeout */
3408             if ((client_ptr -> nx_ptp_client_announce_timeout > 0) &&
3409                 (--client_ptr -> nx_ptp_client_announce_timeout == 0))
3410             {
3411 
3412 #ifdef NX_PTP_ENABLE_MASTER
3413                 if (client_ptr -> nx_ptp_client_role == NX_PTP_CLIENT_ROLE_SLAVE_ONLY)
3414 #endif /* NX_PTP_ENABLE_MASTER */
3415                 {
3416 
3417                     /* no Announce message received from master clock, back to listening state */
3418                     client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
3419                     client_ptr -> nx_ptp_client_delay_req_timer = -1;
3420                     client_ptr -> nx_ptp_client_announce_timeout = -1;
3421 
3422                     /* call handler */
3423                     if (client_ptr -> nx_ptp_client_event_callback)
3424                     {
3425                         client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_TIMEOUT, NX_NULL,
3426                                                                 client_ptr -> nx_ptp_client_event_callback_data);
3427                     }
3428                 }
3429 #ifdef NX_PTP_ENABLE_MASTER
3430                 else
3431                 {
3432 
3433                     /* no Announce message received from master clock, change to master clock. */
3434                     client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_MASTER;
3435 
3436                     /* set timeout for announce and sync */
3437                     client_ptr -> ptp_master.nx_ptp_client_master_announce_timer = NX_PTP_CLIENT_ANNOUNCE_INTERVAL;
3438                     client_ptr -> nx_ptp_client_sync_timer = NX_PTP_CLIENT_SYNC_INTERVAL;
3439                     NX_PTP_DEBUG_PRINTF(("PTP: recommend local clock to be master\r\n"));
3440 
3441                     client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER,
3442                                                                &client_ptr -> ptp_master,
3443                                                                client_ptr -> nx_ptp_client_event_callback_data);
3444                 }
3445 #endif /* NX_PTP_ENABLE_MASTER */
3446             }
3447 
3448             /* delay req interval timer */
3449             if ((client_ptr -> nx_ptp_client_delay_req_timer > 0) &&
3450                 (--client_ptr -> nx_ptp_client_delay_req_timer == 0))
3451             {
3452 
3453                 /* set flag */
3454                 client_ptr -> nx_ptp_client_delay_req_flag = 1;
3455             }
3456 #endif
3457         }
3458     }
3459 
3460     /* set stopped state */
3461     TX_DISABLE
3462     client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPED;
3463     TX_RESTORE
3464 }
3465 
3466 
3467 /**************************************************************************/
3468 /*                                                                        */
3469 /*  FUNCTION                                               RELEASE        */
3470 /*                                                                        */
3471 /*    _nxe_ptp_client_create                              PORTABLE C      */
3472 /*                                                           6.1.3        */
3473 /*  AUTHOR                                                                */
3474 /*                                                                        */
3475 /*    Yuxin Zhou, Microsoft Corporation                                   */
3476 /*                                                                        */
3477 /*  DESCRIPTION                                                           */
3478 /*                                                                        */
3479 /*    This function checks for errors on the PTP client create service.   */
3480 /*                                                                        */
3481 /*  INPUT                                                                 */
3482 /*                                                                        */
3483 /*    client_ptr                            Pointer to PTP client         */
3484 /*    ip_ptr                                Pointer to client IP instance */
3485 /*    interface_index                       Index of PTP network interface*/
3486 /*    packet_pool_ptr                       Pointer to client packet pool */
3487 /*    thread_priority                       Priority of PTP thread        */
3488 /*    thread_stack                          Pointer to thread stack       */
3489 /*    stack_size                            Size of thread stack          */
3490 /*    clock_callback                        PTP clock callback            */
3491 /*    clock_callback_data                   Data for the clock callback   */
3492 /*                                                                        */
3493 /*  OUTPUT                                                                */
3494 /*                                                                        */
3495 /*    status                                Completion status             */
3496 /*                                                                        */
3497 /*  CALLS                                                                 */
3498 /*                                                                        */
3499 /*    _nx_ptp_client_create                 Actual create service         */
3500 /*                                                                        */
3501 /*  CALLED BY                                                             */
3502 /*                                                                        */
3503 /*    Application                                                         */
3504 /*                                                                        */
3505 /*  RELEASE HISTORY                                                       */
3506 /*                                                                        */
3507 /*    DATE              NAME                      DESCRIPTION             */
3508 /*                                                                        */
3509 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3510 /*                                                                        */
3511 /**************************************************************************/
3512 UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
3513                             NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
3514                             NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
3515 {
3516 
3517     /* Check input parameters.  */
3518     if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) ||
3519         (thread_stack == NX_NULL) || (stack_size == 0) || (clock_callback == NX_NULL))
3520     {
3521 
3522         /* Return error status.  */
3523         return(NX_PTR_ERROR);
3524     }
3525 
3526     /* Check for invalid network interface input. */
3527     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
3528     {
3529         return(NX_INVALID_INTERFACE);
3530     }
3531 
3532     /* Check for appropriate caller.  */
3533     NX_THREADS_ONLY_CALLER_CHECKING
3534 
3535     /* Call the actual function.  */
3536     return _nx_ptp_client_create(client_ptr, ip_ptr, interface_index, packet_pool_ptr, thread_priority,
3537                                  thread_stack, stack_size, clock_callback, clock_callback_data);
3538 }
3539 
3540 
3541 /**************************************************************************/
3542 /*                                                                        */
3543 /*  FUNCTION                                               RELEASE        */
3544 /*                                                                        */
3545 /*    _nx_ptp_client_create                               PORTABLE C      */
3546 /*                                                           6.4.0        */
3547 /*  AUTHOR                                                                */
3548 /*                                                                        */
3549 /*    Yuxin Zhou, Microsoft Corporation                                   */
3550 /*                                                                        */
3551 /*  DESCRIPTION                                                           */
3552 /*                                                                        */
3553 /*    This function creates the PTP client.                               */
3554 /*                                                                        */
3555 /*  INPUT                                                                 */
3556 /*                                                                        */
3557 /*    client_ptr                            Pointer to PTP client         */
3558 /*    ip_ptr                                Pointer to client IP instance */
3559 /*    interface_index                       Index of PTP network interface*/
3560 /*    packet_pool_ptr                       Pointer to client packet pool */
3561 /*    thread_priority                       Priority of PTP thread        */
3562 /*    thread_stack                          Pointer to thread stack       */
3563 /*    stack_size                            Size of thread stack          */
3564 /*    clock_callback                        PTP clock callback            */
3565 /*    clock_callback_data                   Data for the clock callback   */
3566 /*                                                                        */
3567 /*  OUTPUT                                                                */
3568 /*                                                                        */
3569 /*    status                                Completion status             */
3570 /*                                                                        */
3571 /*  CALLS                                                                 */
3572 /*                                                                        */
3573 /*    memset                                Reset memory                  */
3574 /*    [clock_callback]                      Initialize clock              */
3575 /*    tx_event_flags_create                 Create PTP event flags        */
3576 /*    tx_event_flags_delete                 Delete PTP event flags        */
3577 /*    nx_udp_socket_create                  Create a UDP socket           */
3578 /*    nx_udp_socket_delete                  Delete a UDP socket           */
3579 /*    nx_udp_socket_receive_notify          Set UDP receive notify        */
3580 /*    tx_timer_create                       Create a timer                */
3581 /*    tx_timer_delete                       Delete a timer                */
3582 /*                                                                        */
3583 /*  CALLED BY                                                             */
3584 /*                                                                        */
3585 /*    Application                                                         */
3586 /*                                                                        */
3587 /*  RELEASE HISTORY                                                       */
3588 /*                                                                        */
3589 /*    DATE              NAME                      DESCRIPTION             */
3590 /*                                                                        */
3591 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3592 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
3593 /*                                            supported gPTP profile,     */
3594 /*                                            resulting in version 6.4.0  */
3595 /*                                                                        */
3596 /**************************************************************************/
3597 UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
3598                            NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
3599                            NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
3600 {
3601 UINT status;
3602 
3603     /* Null the members of NX_PTP_CLIENT.  */
3604     memset(client_ptr, 0, sizeof(NX_PTP_CLIENT));
3605 
3606     /* Set the Client ID to indicate the PTP client thread is ready.  */
3607     client_ptr -> nx_ptp_client_id = NX_PTP_CLIENT_ID;
3608 
3609     /* Set the IP instance.  */
3610     client_ptr -> nx_ptp_client_ip_ptr = ip_ptr;
3611 
3612     /* Set the PTP network interface. */
3613     client_ptr -> nx_ptp_client_interface_index = interface_index;
3614 
3615     /* Set the packet pool, check for minimal packet size requirement. */
3616     if (packet_pool_ptr -> nx_packet_pool_payload_size <
3617         (NX_PTP_PACKET + NX_PTP_CLIENT_PACKET_DATA_SIZE))
3618     {
3619         return(NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD);
3620     }
3621     client_ptr -> nx_ptp_client_packet_pool_ptr = packet_pool_ptr;
3622 
3623     /* Initialize callback function.  */
3624     status = clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_INIT, NX_NULL, NX_NULL, clock_callback_data);
3625     if (status)
3626     {
3627 
3628         /* Fail to initialize clock in callback function.  */
3629         return(NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE);
3630     }
3631 
3632     /* Set the PTP clock callback */
3633     client_ptr -> nx_ptp_client_clock_callback = clock_callback;
3634     client_ptr -> nx_ptp_client_clock_callback_data = clock_callback_data;
3635 
3636     /* By default, the PTP client will run in slave only mode.  */
3637     client_ptr -> nx_ptp_client_role = NX_PTP_CLIENT_ROLE_SLAVE_ONLY;
3638 
3639     /* create the internal PTP event flag object.  */
3640     status = tx_event_flags_create(&(client_ptr -> nx_ptp_client_events), "NetX PTP event flag");
3641     if (status != TX_SUCCESS)
3642     {
3643         return(status);
3644     }
3645 
3646 #if NX_PTP_CLIENT_TRANSPORT_UDP
3647     /* create the general socket */
3648     status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_general_socket,
3649                                  "NetX PTP Client general socket", NX_IP_NORMAL,
3650                                  NX_DONT_FRAGMENT, NX_PTP_TIME_TO_LIVE,
3651                                  NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
3652     if (status != NX_SUCCESS)
3653     {
3654         tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
3655         return(status);
3656     }
3657     client_ptr -> nx_ptp_client_general_socket.nx_udp_socket_reserved_ptr = client_ptr;
3658     nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_general_socket, _nx_ptp_client_socket_receive_notify);
3659 
3660     /* create the event socket */
3661     status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_event_socket,
3662                                   "NetX PTP Client event socket", NX_IP_NORMAL, NX_DONT_FRAGMENT,
3663                                   NX_PTP_TIME_TO_LIVE,
3664                                   NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
3665     if (status != NX_SUCCESS)
3666     {
3667         nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
3668         tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
3669         return(status);
3670     }
3671     client_ptr -> nx_ptp_client_event_socket.nx_udp_socket_reserved_ptr = client_ptr;
3672     nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_event_socket, _nx_ptp_client_socket_receive_notify);
3673 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
3674 
3675     /* create the timer */
3676     status = tx_timer_create(&client_ptr -> nx_ptp_client_timer,
3677                                 "NetX PTP Client timer",
3678                                 _nx_ptp_client_timer_handler,
3679                                 (ULONG)client_ptr,
3680                                 TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
3681                                 TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
3682                                 TX_NO_ACTIVATE);
3683     if (status != TX_SUCCESS)
3684     {
3685 #if NX_PTP_CLIENT_TRANSPORT_UDP
3686         nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
3687         nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
3688 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
3689         tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
3690         return(status);
3691     }
3692 
3693     /* create the Client thread */
3694     status = tx_thread_create(&client_ptr -> nx_ptp_client_thread,
3695                               "NetX PTP Client", _nx_ptp_client_thread_entry,
3696                               (ULONG)client_ptr, thread_stack, stack_size,
3697                               thread_priority, thread_priority,
3698                               NX_PTP_CLIENT_THREAD_TIME_SLICE, TX_DONT_START);
3699     if (status != TX_SUCCESS)
3700     {
3701 #if NX_PTP_CLIENT_TRANSPORT_UDP
3702         nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
3703         nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
3704 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
3705         tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
3706         tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
3707         return(status);
3708     }
3709 
3710     /* return Success */
3711     return(NX_SUCCESS);
3712 }
3713 
3714 /**************************************************************************/
3715 /*                                                                        */
3716 /*  FUNCTION                                               RELEASE        */
3717 /*                                                                        */
3718 /*    _nxe_ptp_client_delete                              PORTABLE C      */
3719 /*                                                           6.1.3        */
3720 /*  AUTHOR                                                                */
3721 /*                                                                        */
3722 /*    Yuxin Zhou, Microsoft Corporation                                   */
3723 /*                                                                        */
3724 /*  DESCRIPTION                                                           */
3725 /*                                                                        */
3726 /*    This function checks for errors on the PTP client delete service.   */
3727 /*                                                                        */
3728 /*  INPUT                                                                 */
3729 /*                                                                        */
3730 /*    client_ptr                            Pointer to PTP client         */
3731 /*                                                                        */
3732 /*  OUTPUT                                                                */
3733 /*                                                                        */
3734 /*    status                                Completion status             */
3735 /*                                                                        */
3736 /*  CALLS                                                                 */
3737 /*                                                                        */
3738 /*    _nx_ptp_client_delete                 Actual delete service         */
3739 /*                                                                        */
3740 /*  CALLED BY                                                             */
3741 /*                                                                        */
3742 /*    Application                                                         */
3743 /*                                                                        */
3744 /*  RELEASE HISTORY                                                       */
3745 /*                                                                        */
3746 /*    DATE              NAME                      DESCRIPTION             */
3747 /*                                                                        */
3748 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3749 /*                                                                        */
3750 /**************************************************************************/
3751 UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
3752 {
3753 
3754     /* Check input parameters.  */
3755     if (client_ptr == NX_NULL)
3756     {
3757 
3758         /* Return error status.  */
3759         return(NX_PTR_ERROR);
3760     }
3761 
3762     /* Check for appropriate caller.  */
3763     NX_THREADS_ONLY_CALLER_CHECKING
3764 
3765     /* Call the actual function.  */
3766     return(_nx_ptp_client_delete(client_ptr));
3767 }
3768 
3769 
3770 /**************************************************************************/
3771 /*                                                                        */
3772 /*  FUNCTION                                               RELEASE        */
3773 /*                                                                        */
3774 /*    _nx_ptp_client_delete                               PORTABLE C      */
3775 /*                                                           6.4.0        */
3776 /*  AUTHOR                                                                */
3777 /*                                                                        */
3778 /*    Yuxin Zhou, Microsoft Corporation                                   */
3779 /*                                                                        */
3780 /*  DESCRIPTION                                                           */
3781 /*                                                                        */
3782 /*    This function deletes the PTP client.                               */
3783 /*                                                                        */
3784 /*  INPUT                                                                 */
3785 /*                                                                        */
3786 /*    client_ptr                            Pointer to PTP client         */
3787 /*                                                                        */
3788 /*  OUTPUT                                                                */
3789 /*                                                                        */
3790 /*    status                                Completion status             */
3791 /*                                                                        */
3792 /*  CALLS                                                                 */
3793 /*                                                                        */
3794 /*    _nx_ptp_client_stop                   Stop PTP service              */
3795 /*    tx_thread_suspend                     Suspend PTP thread            */
3796 /*    tx_thread_terminate                   Terminate PTP thread          */
3797 /*    tx_thread_delete                      Delete PTP thread             */
3798 /*    tx_event_flags_delete                 Delete PTP event flags        */
3799 /*    nx_udp_socket_delete                  Delete a UDP socket           */
3800 /*    tx_timer_delete                       Delete a timer                */
3801 /*                                                                        */
3802 /*  CALLED BY                                                             */
3803 /*                                                                        */
3804 /*    Application                                                         */
3805 /*                                                                        */
3806 /*  RELEASE HISTORY                                                       */
3807 /*                                                                        */
3808 /*    DATE              NAME                      DESCRIPTION             */
3809 /*                                                                        */
3810 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3811 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
3812 /*                                            supported gPTP profile,     */
3813 /*                                            resulting in version 6.4.0  */
3814 /*                                                                        */
3815 /**************************************************************************/
3816 UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
3817 {
3818 
3819     /* Ensure the Client is stopped */
3820     _nx_ptp_client_stop(client_ptr);
3821 
3822     /* Suspend the Client thread.  */
3823     tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
3824 
3825     /* Terminate Client thread. */
3826     tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
3827 
3828     /* Delete Client thread.  */
3829     tx_thread_delete(&client_ptr -> nx_ptp_client_thread);
3830 
3831     /* Delete the timer */
3832     tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
3833 
3834 #if NX_PTP_CLIENT_TRANSPORT_UDP
3835     /* Delete the general socket */
3836     nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
3837 
3838     /* Delete the event socket */
3839     nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
3840 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
3841 
3842     /* Delete the event flag */
3843     tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
3844 
3845     /* return Success */
3846     return(NX_SUCCESS);
3847 }
3848 
3849 
3850 /**************************************************************************/
3851 /*                                                                        */
3852 /*  FUNCTION                                               RELEASE        */
3853 /*                                                                        */
3854 /*    _nxe_ptp_client_start                               PORTABLE C      */
3855 /*                                                           6.1.3        */
3856 /*  AUTHOR                                                                */
3857 /*                                                                        */
3858 /*    Yuxin Zhou, Microsoft Corporation                                   */
3859 /*                                                                        */
3860 /*  DESCRIPTION                                                           */
3861 /*                                                                        */
3862 /*    This function checks for errors on the PTP client start service.    */
3863 /*                                                                        */
3864 /*  INPUT                                                                 */
3865 /*                                                                        */
3866 /*    client_ptr                            Pointer to PTP client         */
3867 /*    client_port_identity_ptr              Pointer to client port and    */
3868 /*                                            identity                    */
3869 /*    client_port_identity_length           Length of client port and     */
3870 /*                                            identity                    */
3871 /*    domain                                PTP clock domain              */
3872 /*    transport_specific                    Transport specific            */
3873 /*    event_callback                        Event callback                */
3874 /*    event_callback_data                   Data for the event callback   */
3875 /*                                                                        */
3876 /*  OUTPUT                                                                */
3877 /*                                                                        */
3878 /*    status                                Completion status             */
3879 /*                                                                        */
3880 /*  CALLS                                                                 */
3881 /*                                                                        */
3882 /*    _nx_ptp_client_start                  Actual start service          */
3883 /*                                                                        */
3884 /*  CALLED BY                                                             */
3885 /*                                                                        */
3886 /*    Application                                                         */
3887 /*                                                                        */
3888 /*  RELEASE HISTORY                                                       */
3889 /*                                                                        */
3890 /*    DATE              NAME                      DESCRIPTION             */
3891 /*                                                                        */
3892 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3893 /*                                                                        */
3894 /**************************************************************************/
3895 UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
3896                            UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
3897                            VOID *event_callback_data)
3898 {
3899 
3900     /* Check input parameters.  */
3901     if ((client_ptr == NX_NULL) ||
3902         ((client_port_identity_ptr == NX_NULL) && (client_port_identity_length != 0)) ||
3903         ((client_port_identity_ptr != NX_NULL) && (client_port_identity_length != NX_PTP_CLOCK_PORT_IDENTITY_SIZE)))
3904     {
3905 
3906         /* Return error status.  */
3907         return(NX_PTR_ERROR);
3908     }
3909 
3910     /* Check for appropriate caller.  */
3911     NX_THREADS_ONLY_CALLER_CHECKING
3912 
3913     /* Call the actual function.  */
3914     return(_nx_ptp_client_start(client_ptr, client_port_identity_ptr, client_port_identity_length,
3915                                 domain, transport_specific, event_callback, event_callback_data));
3916 }
3917 
3918 
3919 /**************************************************************************/
3920 /*                                                                        */
3921 /*  FUNCTION                                               RELEASE        */
3922 /*                                                                        */
3923 /*    _nx_ptp_client_start                                PORTABLE C      */
3924 /*                                                           6.4.0        */
3925 /*  AUTHOR                                                                */
3926 /*                                                                        */
3927 /*    Yuxin Zhou, Microsoft Corporation                                   */
3928 /*                                                                        */
3929 /*  DESCRIPTION                                                           */
3930 /*                                                                        */
3931 /*    This function starts the PTP client.                                */
3932 /*                                                                        */
3933 /*  INPUT                                                                 */
3934 /*                                                                        */
3935 /*    client_ptr                            Pointer to PTP client         */
3936 /*    client_port_identity_ptr              Pointer to client port and    */
3937 /*                                            identity                    */
3938 /*    client_port_identity_length           Length of client port and     */
3939 /*                                            identity                    */
3940 /*    domain                                PTP clock domain              */
3941 /*    transport_specific                    Transport specific            */
3942 /*    event_callback                        Event callback                */
3943 /*    event_callback_data                   Data for the event callback   */
3944 /*                                                                        */
3945 /*  OUTPUT                                                                */
3946 /*                                                                        */
3947 /*    status                                Completion status             */
3948 /*                                                                        */
3949 /*  CALLS                                                                 */
3950 /*                                                                        */
3951 /*    tx_thread_suspend                     Suspend PTP thread            */
3952 /*    tx_thread_terminate                   Terminate PTP thread          */
3953 /*    tx_thread_reset                       Reset PTP thread              */
3954 /*    tx_thread_resume                      Resume PTP thread             */
3955 /*    memcpy                                Copy memory                   */
3956 /*    nx_ip_interface_physical_address_get  Get physical address          */
3957 /*    nx_udp_socket_bind                    Bind UDP port                 */
3958 /*    nx_ipv4_multicast_interface_join      Join IPv4 multicast group     */
3959 /*    nxd_ipv6_multicast_interface_join     Join IPv6 multicast group     */
3960 /*    tx_timer_activate                     Activate timer                */
3961 /*    _nx_ptp_client_stop                   Stop PTP service              */
3962 /*                                                                        */
3963 /*  CALLED BY                                                             */
3964 /*                                                                        */
3965 /*    Application                                                         */
3966 /*                                                                        */
3967 /*  RELEASE HISTORY                                                       */
3968 /*                                                                        */
3969 /*    DATE              NAME                      DESCRIPTION             */
3970 /*                                                                        */
3971 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
3972 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
3973 /*                                            supported gPTP profile,     */
3974 /*                                            supported master clock,     */
3975 /*                                            resulting in version 6.4.0  */
3976 /*                                                                        */
3977 /**************************************************************************/
3978 UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
3979                           UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
3980                           VOID *event_callback_data)
3981 {
3982 TX_INTERRUPT_SAVE_AREA
3983 UINT  state;
3984 UINT  status;
3985 ULONG msw, lsw;
3986 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
3987 NXD_ADDRESS maddr;
3988 #endif
3989 
3990     NX_PARAMETER_NOT_USED(client_port_identity_length);
3991 
3992     /* Check if Client is running */
3993     TX_DISABLE
3994     state = client_ptr -> nx_ptp_client_thread_state;
3995     if (state == NX_PTP_CLIENT_THREAD_IDLE)
3996     {
3997         client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_RUNNING;
3998     }
3999     TX_RESTORE
4000     if (state != NX_PTP_CLIENT_THREAD_IDLE)
4001     {
4002 
4003         /* Client is already running */
4004         return(NX_PTP_CLIENT_ALREADY_STARTED);
4005     }
4006 
4007     /* ensure the thread is terminated */
4008     tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
4009     tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
4010 
4011     /* save the client parameters */
4012     client_ptr -> nx_ptp_client_domain    = (UCHAR)domain;
4013     client_ptr -> nx_ptp_client_transport_specific = (UCHAR)transport_specific;
4014     client_ptr -> nx_ptp_client_event_callback = event_callback;
4015     client_ptr -> nx_ptp_client_event_callback_data = event_callback_data;
4016     client_ptr -> nx_ptp_client_delay.nanosecond = NX_PTP_CLIENT_DELAY_THRESH;
4017 
4018     /* reset and resume the thread */
4019     status = tx_thread_reset(&client_ptr -> nx_ptp_client_thread);
4020     if (status != TX_SUCCESS)
4021     {
4022         TX_DISABLE
4023         client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
4024         TX_RESTORE
4025 
4026         return(status);
4027     }
4028     tx_thread_resume(&client_ptr -> nx_ptp_client_thread);
4029 
4030     /* set the client port and identity */
4031     if (client_port_identity_ptr != NX_NULL)
4032     {
4033 
4034         /* copy provided identifier */
4035         memcpy(client_ptr -> nx_ptp_client_port_identity, client_port_identity_ptr,
4036                NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
4037     }
4038     else
4039     {
4040 
4041         /* get MAC address of interface */
4042         status = nx_ip_interface_physical_address_get(client_ptr -> nx_ptp_client_ip_ptr,
4043                                                       client_ptr -> nx_ptp_client_interface_index,
4044                                                       &msw, &lsw);
4045         if (status == TX_SUCCESS)
4046         {
4047             /* convert 48-bit MAC address to 64-bit EUI */
4048             client_ptr -> nx_ptp_client_port_identity[0] = (UCHAR)(msw >> 8);
4049             client_ptr -> nx_ptp_client_port_identity[1] = (UCHAR)msw;
4050             client_ptr -> nx_ptp_client_port_identity[2] = (UCHAR)(lsw >> 24);
4051             client_ptr -> nx_ptp_client_port_identity[3] = 0xff;
4052             client_ptr -> nx_ptp_client_port_identity[4] = 0xfe;
4053             client_ptr -> nx_ptp_client_port_identity[5] = (UCHAR)(lsw >> 16);
4054             client_ptr -> nx_ptp_client_port_identity[6] = (UCHAR)(lsw >> 8);
4055             client_ptr -> nx_ptp_client_port_identity[7] = (UCHAR)lsw;
4056 
4057             /* set default port number (1) */
4058             client_ptr -> nx_ptp_client_port_identity[8] = 0;
4059             client_ptr -> nx_ptp_client_port_identity[9] = 1;
4060         }
4061     }
4062 
4063 #if NX_PTP_CLIENT_TRANSPORT_UDP
4064     /* bind the general socket */
4065     if (status == TX_SUCCESS)
4066     {
4067         status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
4068                                     NX_PTP_GENERAL_UDP_PORT, NX_NO_WAIT);
4069     }
4070 
4071     /* bind the event socket */
4072     if (status == TX_SUCCESS)
4073     {
4074         status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
4075                                     NX_PTP_EVENT_UDP_PORT, NX_NO_WAIT);
4076     }
4077 
4078     /* join the multicast groups */
4079     if (status == TX_SUCCESS)
4080     {
4081         status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
4082                                                   NX_PTP_IPV4_MULTICAST_ADDR,
4083                                                   client_ptr -> nx_ptp_client_interface_index);
4084         if (status == TX_SUCCESS)
4085         {
4086             status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
4087                                                   NX_PTP_IPV4_P2P_MULTICAST_ADDR,
4088                                                   client_ptr -> nx_ptp_client_interface_index);
4089             if (status == TX_SUCCESS)
4090             {
4091                 client_ptr -> nx_ptp_client_ipv4_group_joined = NX_TRUE;
4092             }
4093         }
4094     }
4095 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
4096     if (status == TX_SUCCESS)
4097     {
4098         NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
4099         status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
4100                                                    &maddr, client_ptr -> nx_ptp_client_interface_index);
4101         if (status == TX_SUCCESS)
4102         {
4103             NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(&maddr);
4104             status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
4105                                                    &maddr, client_ptr -> nx_ptp_client_interface_index);
4106             if (status == TX_SUCCESS)
4107             {
4108                 NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
4109                 status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
4110                                                    &maddr, client_ptr -> nx_ptp_client_interface_index);
4111 
4112                 if (status == TX_SUCCESS)
4113                 {
4114                     client_ptr -> nx_ptp_client_ipv6_group_joined = NX_TRUE;
4115                 }
4116             }
4117         }
4118         else if ((status == NX_NOT_SUPPORTED) && (client_ptr -> nx_ptp_client_ipv4_group_joined))
4119         {
4120 
4121             /* IPv6 not enabled, use IPv4 only */
4122             status = TX_SUCCESS;
4123         }
4124     }
4125 #endif
4126 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
4127 
4128 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
4129     /* set link layer receive notification */
4130     status = nx_link_packet_receive_callback_add(client_ptr -> nx_ptp_client_ip_ptr,
4131                                                  client_ptr -> nx_ptp_client_interface_index,
4132                                                  &(client_ptr -> nx_ptp_client_link_queue),
4133                                                  NX_PTP_ETHERNET_TYPE,
4134                                                  _nx_ptp_client_ethernet_receive_notify, client_ptr);
4135     if (status != NX_SUCCESS)
4136     {
4137         return(status);
4138     }
4139 
4140     status = nx_link_multicast_join(client_ptr -> nx_ptp_client_ip_ptr,
4141                                     client_ptr -> nx_ptp_client_interface_index,
4142                                     NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_MSB,
4143                                     NX_PTP_ETHERNET_ALL_MULTICAST_ADDR_LSB);
4144     if (status != NX_SUCCESS)
4145     {
4146         return(status);
4147     }
4148 
4149     status = nx_link_multicast_join(client_ptr -> nx_ptp_client_ip_ptr,
4150                                     client_ptr -> nx_ptp_client_interface_index,
4151                                     NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_MSB,
4152                                     NX_PTP_ETHERNET_P2P_MULTICAST_ADDR_LSB);
4153     if (status != NX_SUCCESS)
4154     {
4155         return(status);
4156     }
4157 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
4158 
4159     /* activate the Client timer */
4160     if (status == TX_SUCCESS)
4161     {
4162 
4163         /* activate the timer */
4164         status = tx_timer_activate(&client_ptr -> nx_ptp_client_timer);
4165     }
4166 
4167     /* stop the client thread in case of error */
4168     if (status != TX_SUCCESS)
4169     {
4170         _nx_ptp_client_stop(client_ptr);
4171 
4172         /* return failure */
4173         return(status);
4174     }
4175 
4176     /* return Success */
4177     return(NX_SUCCESS);
4178 }
4179 
4180 
4181 /**************************************************************************/
4182 /*                                                                        */
4183 /*  FUNCTION                                               RELEASE        */
4184 /*                                                                        */
4185 /*    _nxe_ptp_client_stop                                PORTABLE C      */
4186 /*                                                           6.1.3        */
4187 /*  AUTHOR                                                                */
4188 /*                                                                        */
4189 /*    Yuxin Zhou, Microsoft Corporation                                   */
4190 /*                                                                        */
4191 /*  DESCRIPTION                                                           */
4192 /*                                                                        */
4193 /*    This function checks for errors on the PTP client stop service.     */
4194 /*                                                                        */
4195 /*  INPUT                                                                 */
4196 /*                                                                        */
4197 /*    client_ptr                            Pointer to PTP client         */
4198 /*                                                                        */
4199 /*  OUTPUT                                                                */
4200 /*                                                                        */
4201 /*    status                                Completion status             */
4202 /*                                                                        */
4203 /*  CALLS                                                                 */
4204 /*                                                                        */
4205 /*    _nx_ptp_client_stop                   Actual stop service           */
4206 /*                                                                        */
4207 /*  CALLED BY                                                             */
4208 /*                                                                        */
4209 /*    Application                                                         */
4210 /*                                                                        */
4211 /*  RELEASE HISTORY                                                       */
4212 /*                                                                        */
4213 /*    DATE              NAME                      DESCRIPTION             */
4214 /*                                                                        */
4215 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4216 /*                                                                        */
4217 /**************************************************************************/
4218 UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
4219 {
4220 
4221     /* Check input parameters.  */
4222     if (client_ptr == NX_NULL)
4223     {
4224 
4225         /* Return error status.  */
4226         return(NX_PTR_ERROR);
4227     }
4228 
4229     /* Check for appropriate caller.  */
4230     NX_THREADS_ONLY_CALLER_CHECKING
4231 
4232     /* Call the actual function.  */
4233     return(_nx_ptp_client_stop(client_ptr));
4234 }
4235 
4236 
4237 /**************************************************************************/
4238 /*                                                                        */
4239 /*  FUNCTION                                               RELEASE        */
4240 /*                                                                        */
4241 /*    _nx_ptp_client_stop                                 PORTABLE C      */
4242 /*                                                           6.4.0        */
4243 /*  AUTHOR                                                                */
4244 /*                                                                        */
4245 /*    Yuxin Zhou, Microsoft Corporation                                   */
4246 /*                                                                        */
4247 /*  DESCRIPTION                                                           */
4248 /*                                                                        */
4249 /*    This function stops the PTP client.                                 */
4250 /*                                                                        */
4251 /*  INPUT                                                                 */
4252 /*                                                                        */
4253 /*    client_ptr                            Pointer to PTP client         */
4254 /*                                                                        */
4255 /*  OUTPUT                                                                */
4256 /*                                                                        */
4257 /*    status                                Completion status             */
4258 /*                                                                        */
4259 /*  CALLS                                                                 */
4260 /*                                                                        */
4261 /*    tx_timer_deactivate                   Deactivate timer              */
4262 /*    nx_udp_socket_unbind                  Unbind UDP port               */
4263 /*    nx_ipv4_multicast_interface_leave     Leave IPv4 multicast group    */
4264 /*    nxd_ipv6_multicast_interface_leave    Leave IPv6 multicast group    */
4265 /*    tx_event_flags_set                    Set PTP timer event           */
4266 /*    tx_thread_sleep                       Thread sleep                  */
4267 /*                                                                        */
4268 /*  CALLED BY                                                             */
4269 /*                                                                        */
4270 /*    Application                                                         */
4271 /*                                                                        */
4272 /*  RELEASE HISTORY                                                       */
4273 /*                                                                        */
4274 /*    DATE              NAME                      DESCRIPTION             */
4275 /*                                                                        */
4276 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4277 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
4278 /*                                            supported gPTP profile,     */
4279 /*                                            resulting in version 6.4.0  */
4280 /*                                                                        */
4281 /**************************************************************************/
4282 UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
4283 {
4284 TX_INTERRUPT_SAVE_AREA
4285 UINT state;
4286 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
4287 NXD_ADDRESS maddr;
4288 #endif
4289 
4290     /* Check if Client is running */
4291     TX_DISABLE
4292     state = client_ptr -> nx_ptp_client_thread_state;
4293     if (state == NX_PTP_CLIENT_THREAD_RUNNING)
4294     {
4295         client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPING;
4296     }
4297     TX_RESTORE
4298     if ((state != NX_PTP_CLIENT_THREAD_RUNNING) &&
4299         (state != NX_PTP_CLIENT_THREAD_STOPPED))
4300     {
4301 
4302         /* Client is not running */
4303         return(NX_PTP_CLIENT_NOT_STARTED);
4304     }
4305 
4306     /* deactivate the timer */
4307     tx_timer_deactivate(&client_ptr -> nx_ptp_client_timer);
4308 
4309 #if NX_PTP_CLIENT_TRANSPORT_UDP
4310     /* unbind the sockets */
4311     nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
4312     nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
4313 
4314     /* leave multicast groups */
4315     if (client_ptr -> nx_ptp_client_ipv4_group_joined)
4316     {
4317         nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
4318                                           NX_PTP_IPV4_MULTICAST_ADDR,
4319                                           client_ptr -> nx_ptp_client_interface_index);
4320         nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
4321                                           NX_PTP_IPV4_P2P_MULTICAST_ADDR,
4322                                           client_ptr -> nx_ptp_client_interface_index);
4323         client_ptr -> nx_ptp_client_ipv4_group_joined = NX_FALSE;
4324     }
4325 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
4326     if (client_ptr -> nx_ptp_client_ipv6_group_joined)
4327     {
4328         NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
4329         nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
4330                                            &maddr, client_ptr -> nx_ptp_client_interface_index);
4331         NX_PTP_IPV6_P2P_MULTICAST_ADDR_SET(&maddr);
4332         nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
4333                                            &maddr, client_ptr -> nx_ptp_client_interface_index);
4334         client_ptr -> nx_ptp_client_ipv6_group_joined = NX_FALSE;
4335     }
4336 #endif
4337 #endif /* NX_PTP_CLIENT_TRANSPORT_UDP */
4338 
4339 #if NX_PTP_CLIENT_TRANSPORT_ETHERNET
4340     nx_link_packet_receive_callback_remove(client_ptr -> nx_ptp_client_ip_ptr,
4341                                            client_ptr -> nx_ptp_client_interface_index,
4342                                            &(client_ptr -> nx_ptp_client_link_queue));
4343 #endif /* NX_PTP_CLIENT_TRANSPORT_ETHERNET */
4344 
4345     /* send STOP message */
4346     tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_STOP_EVENT, TX_OR);
4347 
4348     /* wait for thread termination */
4349     while (state != NX_PTP_CLIENT_THREAD_STOPPED)
4350     {
4351         tx_thread_sleep(1);
4352         TX_DISABLE
4353         state = client_ptr -> nx_ptp_client_thread_state;
4354         TX_RESTORE
4355     }
4356 
4357     /* set Idle state */
4358     TX_DISABLE
4359     client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
4360     TX_RESTORE
4361 
4362     /* return Success */
4363     return(NX_SUCCESS);
4364 }
4365 
4366 #ifdef NX_PTP_ENABLE_MASTER
4367 /**************************************************************************/
4368 /*                                                                        */
4369 /*  FUNCTION                                               RELEASE        */
4370 /*                                                                        */
4371 /*    _nxe_ptp_client_master_enable                       PORTABLE C      */
4372 /*                                                           6.4.0        */
4373 /*  AUTHOR                                                                */
4374 /*                                                                        */
4375 /*    Tiejun Zhou, Microsoft Corporation                                  */
4376 /*                                                                        */
4377 /*  DESCRIPTION                                                           */
4378 /*                                                                        */
4379 /*    This function performs error checking for enabling master feature   */
4380 /*    for local PTP clock.                                                */
4381 /*                                                                        */
4382 /*  INPUT                                                                 */
4383 /*                                                                        */
4384 /*    client_ptr                            Pointer to PTP client         */
4385 /*    role                                  Role of PTP clock             */
4386 /*                                            SLAVE_ONLY, MASTER_ONLY or  */
4387 /*                                            SLAVE_AND_MASTER            */
4388 /*    priority1                             Priority1 of master clock     */
4389 /*    priority2                             Priority2 of master clock     */
4390 /*    clock_class                           Class of master clock         */
4391 /*    clock_accuracy                        Accuracy of master clock      */
4392 /*    clock_variance                        Variance of master clock      */
4393 /*    steps_removed                         Steps removed of master clock */
4394 /*    time_source                           Time source of master clock   */
4395 /*                                                                        */
4396 /*  OUTPUT                                                                */
4397 /*                                                                        */
4398 /*    Completion status                                                   */
4399 /*                                                                        */
4400 /*  CALLS                                                                 */
4401 /*                                                                        */
4402 /*    _nx_ptp_client_master_enable          Actual master enable service  */
4403 /*                                                                        */
4404 /*  CALLED BY                                                             */
4405 /*                                                                        */
4406 /*    Application                                                         */
4407 /*                                                                        */
4408 /*  RELEASE HISTORY                                                       */
4409 /*                                                                        */
4410 /*    DATE              NAME                      DESCRIPTION             */
4411 /*                                                                        */
4412 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
4413 /*                                                                        */
4414 /**************************************************************************/
4415 UINT _nxe_ptp_client_master_enable(NX_PTP_CLIENT *client_ptr, UCHAR role, UCHAR priority1, UCHAR priority2,
4416                                    UCHAR clock_class, UCHAR clock_accuracy, USHORT clock_variance,
4417                                    USHORT steps_removed, UCHAR time_source)
4418 {
4419     /* Check input parameters.  */
4420     if (client_ptr == NX_NULL)
4421     {
4422 
4423         /* Return error status.  */
4424         return(NX_PTR_ERROR);
4425     }
4426 
4427     if ((role != NX_PTP_CLIENT_ROLE_MASTER_ONLY) &&
4428         (role != NX_PTP_CLIENT_ROLE_SLAVE_AND_MASTER))
4429     {
4430 
4431         /* Return error status.  */
4432         return(NX_INVALID_PARAMETERS);
4433     }
4434 
4435     /* Check for appropriate caller.  */
4436     NX_THREADS_ONLY_CALLER_CHECKING
4437 
4438     /* Call the actual function.  */
4439     return(_nx_ptp_client_master_enable(client_ptr, role, priority1, priority2, clock_class,
4440                                         clock_accuracy, clock_variance, steps_removed, time_source));
4441 }
4442 
4443 /**************************************************************************/
4444 /*                                                                        */
4445 /*  FUNCTION                                               RELEASE        */
4446 /*                                                                        */
4447 /*    _nx_ptp_client_master_enable                        PORTABLE C      */
4448 /*                                                           6.4.0        */
4449 /*  AUTHOR                                                                */
4450 /*                                                                        */
4451 /*    Tiejun Zhou, Microsoft Corporation                                  */
4452 /*                                                                        */
4453 /*  DESCRIPTION                                                           */
4454 /*                                                                        */
4455 /*    This function enables master feature for local PTP clock.           */
4456 /*                                                                        */
4457 /*  INPUT                                                                 */
4458 /*                                                                        */
4459 /*    client_ptr                            Pointer to PTP client         */
4460 /*    role                                  Role of PTP clock             */
4461 /*                                            SLAVE_ONLY, MASTER_ONLY or  */
4462 /*                                            SLAVE_AND_MASTER            */
4463 /*    priority1                             Priority1 of master clock     */
4464 /*    priority2                             Priority2 of master clock     */
4465 /*    clock_class                           Class of master clock         */
4466 /*    clock_accuracy                        Accuracy of master clock      */
4467 /*    clock_variance                        Variance of master clock      */
4468 /*    steps_removed                         Steps removed of master clock */
4469 /*    time_source                           Time source of master clock   */
4470 /*                                                                        */
4471 /*  OUTPUT                                                                */
4472 /*                                                                        */
4473 /*    Completion status                                                   */
4474 /*                                                                        */
4475 /*  CALLS                                                                 */
4476 /*                                                                        */
4477 /*    None                                                                */
4478 /*                                                                        */
4479 /*  CALLED BY                                                             */
4480 /*                                                                        */
4481 /*    Application                                                         */
4482 /*                                                                        */
4483 /*  RELEASE HISTORY                                                       */
4484 /*                                                                        */
4485 /*    DATE              NAME                      DESCRIPTION             */
4486 /*                                                                        */
4487 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
4488 /*                                                                        */
4489 /**************************************************************************/
4490 UINT _nx_ptp_client_master_enable(NX_PTP_CLIENT *client_ptr, UCHAR role, UCHAR priority1, UCHAR priority2,
4491                                   UCHAR clock_class, UCHAR clock_accuracy, USHORT clock_variance,
4492                                   USHORT steps_removed, UCHAR time_source)
4493 {
4494 
4495     /*
4496      * nx_ptp_master_priority1:                     0 is reserved. Set at 1 for highest priority
4497      * nx_ptp_master_priority2:                     AS2020: 8.6.2.5 The default value for a PTP Relay Instance should be 247.
4498      *                                              The default value for a PTP End Instance should be 248.
4499      * nx_ptp_master_clock_class:                   AS2020: 8.6.2.2 If the value that reflects the LocalClock and ClockSource entities is
4500      *                                              not specified or not known, clockClass is set to 248
4501      * nx_ptp_master_clock_accuracy:                User input.
4502      *                                              AS2020:8.6.2.3 If the value that reflects the LocalClock and ClockSource entities is
4503      *                                              not specified or unknown, clockAccuracy is set to 254 (FE16).
4504      *                                              1588-2019: 7.6.2.6 clockAccuracy reference Table 5 enumerations
4505      * nx_ptp_master_offset_scaled_log_variance:    AS2020:8.6.2.4 If the value that reflects these entities is not specified or not known,
4506      *                                              offsetScaledLogVariance is set to 17258 (436A16)
4507      * nx_ptp_master_sequenceId                     Sequence ID for master starts at 0
4508      */
4509 
4510     client_ptr -> ptp_master.nx_ptp_client_master_address = NX_NULL; /* use client ptr */
4511     client_ptr -> ptp_master.nx_ptp_client_master_port_identity = client_ptr -> nx_ptp_client_port_identity; /* use client port */
4512     client_ptr -> ptp_master.nx_ptp_client_master_grandmaster_identity = client_ptr -> nx_ptp_client_port_identity; /* use client identity */
4513 
4514     client_ptr -> ptp_master.nx_ptp_client_master_priority1 = priority1;
4515     client_ptr -> ptp_master.nx_ptp_client_master_priority2 = priority2;
4516     client_ptr -> ptp_master.nx_ptp_client_master_clock_class = clock_class;
4517     client_ptr -> ptp_master.nx_ptp_client_master_clock_accuracy = clock_accuracy;
4518     client_ptr -> ptp_master.nx_ptp_client_master_offset_scaled_log_variance = clock_variance;
4519     client_ptr -> ptp_master.nx_ptp_client_master_steps_removed = steps_removed;
4520     client_ptr -> ptp_master.nx_ptp_client_master_time_source = time_source;
4521     client_ptr -> ptp_master.nx_ptp_client_master_sequenceId = 0xFFFF;
4522     client_ptr -> ptp_master.nx_ptp_client_master_sync_sequenceId = 0xFFFF;
4523     client_ptr -> nx_ptp_client_role = role;
4524 
4525     /* return Success */
4526     return(NX_SUCCESS);
4527 }
4528 #endif /* NX_PTP_ENABLE_MASTER */
4529 
4530 /**************************************************************************/
4531 /*                                                                        */
4532 /*  FUNCTION                                               RELEASE        */
4533 /*                                                                        */
4534 /*    _nxe_ptp_client_time_get                            PORTABLE C      */
4535 /*                                                           6.1.3        */
4536 /*  AUTHOR                                                                */
4537 /*                                                                        */
4538 /*    Yuxin Zhou, Microsoft Corporation                                   */
4539 /*                                                                        */
4540 /*  DESCRIPTION                                                           */
4541 /*                                                                        */
4542 /*    This function checks for errors on the PTP time get service.        */
4543 /*                                                                        */
4544 /*  INPUT                                                                 */
4545 /*                                                                        */
4546 /*    client_ptr                            Pointer to PTP client         */
4547 /*    time_ptr                              Pointer to PTP time           */
4548 /*                                                                        */
4549 /*  OUTPUT                                                                */
4550 /*                                                                        */
4551 /*    status                                Completion status             */
4552 /*                                                                        */
4553 /*  CALLS                                                                 */
4554 /*                                                                        */
4555 /*    _nx_ptp_client_time_get               Actual time get service       */
4556 /*                                                                        */
4557 /*  CALLED BY                                                             */
4558 /*                                                                        */
4559 /*    Application                                                         */
4560 /*                                                                        */
4561 /*  RELEASE HISTORY                                                       */
4562 /*                                                                        */
4563 /*    DATE              NAME                      DESCRIPTION             */
4564 /*                                                                        */
4565 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4566 /*                                                                        */
4567 /**************************************************************************/
4568 UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
4569 {
4570 
4571     /* Check input parameters.  */
4572     if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
4573     {
4574 
4575         /* Return error status.  */
4576         return(NX_PTR_ERROR);
4577     }
4578 
4579     /* Check for appropriate caller.  */
4580     NX_THREADS_ONLY_CALLER_CHECKING
4581 
4582     /* Call the actual function.  */
4583     return(_nx_ptp_client_time_get(client_ptr, time_ptr));
4584 }
4585 
4586 
4587 /**************************************************************************/
4588 /*                                                                        */
4589 /*  FUNCTION                                               RELEASE        */
4590 /*                                                                        */
4591 /*    _nx_ptp_client_time_get                             PORTABLE C      */
4592 /*                                                           6.1.3        */
4593 /*  AUTHOR                                                                */
4594 /*                                                                        */
4595 /*    Yuxin Zhou, Microsoft Corporation                                   */
4596 /*                                                                        */
4597 /*  DESCRIPTION                                                           */
4598 /*                                                                        */
4599 /*    This function gets the current value of the PTP clock.              */
4600 /*                                                                        */
4601 /*  INPUT                                                                 */
4602 /*                                                                        */
4603 /*    client_ptr                            Pointer to PTP client         */
4604 /*    time_ptr                              Pointer to PTP time           */
4605 /*                                                                        */
4606 /*  OUTPUT                                                                */
4607 /*                                                                        */
4608 /*    status                                Completion status             */
4609 /*                                                                        */
4610 /*  CALLS                                                                 */
4611 /*                                                                        */
4612 /*    None                                                                */
4613 /*                                                                        */
4614 /*  CALLED BY                                                             */
4615 /*                                                                        */
4616 /*    Application                                                         */
4617 /*                                                                        */
4618 /*  RELEASE HISTORY                                                       */
4619 /*                                                                        */
4620 /*    DATE              NAME                      DESCRIPTION             */
4621 /*                                                                        */
4622 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4623 /*                                                                        */
4624 /**************************************************************************/
4625 UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
4626 {
4627 
4628     /* Get the current PTP clock */
4629     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET,
4630                                                time_ptr, NX_NULL,
4631                                                client_ptr -> nx_ptp_client_clock_callback_data);
4632 
4633     /* return Success */
4634     return(NX_SUCCESS);
4635 }
4636 
4637 
4638 /**************************************************************************/
4639 /*                                                                        */
4640 /*  FUNCTION                                               RELEASE        */
4641 /*                                                                        */
4642 /*    _nxe_ptp_client_time_set                            PORTABLE C      */
4643 /*                                                           6.1.3        */
4644 /*  AUTHOR                                                                */
4645 /*                                                                        */
4646 /*    Yuxin Zhou, Microsoft Corporation                                   */
4647 /*                                                                        */
4648 /*  DESCRIPTION                                                           */
4649 /*                                                                        */
4650 /*    This function checks for errors on the PTP time set service.        */
4651 /*                                                                        */
4652 /*  INPUT                                                                 */
4653 /*                                                                        */
4654 /*    client_ptr                            Pointer to PTP client         */
4655 /*    time_ptr                              Pointer to PTP time           */
4656 /*                                                                        */
4657 /*  OUTPUT                                                                */
4658 /*                                                                        */
4659 /*    status                                Completion status             */
4660 /*                                                                        */
4661 /*  CALLS                                                                 */
4662 /*                                                                        */
4663 /*    _nx_ptp_client_time_set               Actual time set service       */
4664 /*                                                                        */
4665 /*  CALLED BY                                                             */
4666 /*                                                                        */
4667 /*    Application                                                         */
4668 /*                                                                        */
4669 /*  RELEASE HISTORY                                                       */
4670 /*                                                                        */
4671 /*    DATE              NAME                      DESCRIPTION             */
4672 /*                                                                        */
4673 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4674 /*                                                                        */
4675 /**************************************************************************/
4676 UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
4677 {
4678 
4679     /* Check input parameters.  */
4680     if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
4681     {
4682 
4683         /* Return error status.  */
4684         return(NX_PTR_ERROR);
4685     }
4686 
4687     /* Check for appropriate caller.  */
4688     NX_THREADS_ONLY_CALLER_CHECKING
4689 
4690     /* Call the actual function.  */
4691     return(_nx_ptp_client_time_set(client_ptr, time_ptr));
4692 }
4693 
4694 
4695 /**************************************************************************/
4696 /*                                                                        */
4697 /*  FUNCTION                                               RELEASE        */
4698 /*                                                                        */
4699 /*    _nx_ptp_client_time_set                             PORTABLE C      */
4700 /*                                                           6.1.3        */
4701 /*  AUTHOR                                                                */
4702 /*                                                                        */
4703 /*    Yuxin Zhou, Microsoft Corporation                                   */
4704 /*                                                                        */
4705 /*  DESCRIPTION                                                           */
4706 /*                                                                        */
4707 /*    This function sets the initial time of the PTP clock.               */
4708 /*                                                                        */
4709 /*  INPUT                                                                 */
4710 /*                                                                        */
4711 /*    client_ptr                            Pointer to PTP client         */
4712 /*    time_ptr                              Pointer to PTP time           */
4713 /*                                                                        */
4714 /*  OUTPUT                                                                */
4715 /*                                                                        */
4716 /*    status                                Completion status             */
4717 /*                                                                        */
4718 /*  CALLS                                                                 */
4719 /*                                                                        */
4720 /*    None                                                                */
4721 /*                                                                        */
4722 /*  CALLED BY                                                             */
4723 /*                                                                        */
4724 /*    Application                                                         */
4725 /*                                                                        */
4726 /*  RELEASE HISTORY                                                       */
4727 /*                                                                        */
4728 /*    DATE              NAME                      DESCRIPTION             */
4729 /*                                                                        */
4730 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4731 /*                                                                        */
4732 /**************************************************************************/
4733 UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
4734 {
4735 TX_INTERRUPT_SAVE_AREA
4736 UINT state;
4737 
4738     /* Check if Client is running */
4739     TX_DISABLE
4740     state = client_ptr -> nx_ptp_client_thread_state;
4741     TX_RESTORE
4742 
4743     if (state != NX_PTP_CLIENT_THREAD_IDLE)
4744     {
4745 
4746         /* Cannot set the clock when the client is running */
4747         return(NX_PTP_CLIENT_ALREADY_STARTED);
4748     }
4749 
4750     /* Set the current PTP clock */
4751     client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET,
4752                                                time_ptr, NX_NULL,
4753                                                client_ptr -> nx_ptp_client_clock_callback_data);
4754 
4755     /* return Success */
4756     return(NX_SUCCESS);
4757 }
4758 
4759 
4760 /**************************************************************************/
4761 /*                                                                        */
4762 /*  FUNCTION                                               RELEASE        */
4763 /*                                                                        */
4764 /*    _nxe_ptp_client_master_info_get                     PORTABLE C      */
4765 /*                                                           6.1.3        */
4766 /*  AUTHOR                                                                */
4767 /*                                                                        */
4768 /*    Yuxin Zhou, Microsoft Corporation                                   */
4769 /*                                                                        */
4770 /*  DESCRIPTION                                                           */
4771 /*                                                                        */
4772 /*    This function checks for errors on the PTP master info get service. */
4773 /*                                                                        */
4774 /*  INPUT                                                                 */
4775 /*                                                                        */
4776 /*    master_ptr                            Pointer to PTP master clock   */
4777 /*    address                               Address of master clock       */
4778 /*    port_identity                         PTP master port and identity  */
4779 /*    port_identity_length                  Length of PTP master port and */
4780 /*                                            identity                    */
4781 /*    priority1                             Priority1 of PTP master clock */
4782 /*    priority2                             Priority2 of PTP master clock */
4783 /*    clock_class                           Class of PTP master clock     */
4784 /*    clock_accuracy                        Accuracy of PTP master clock  */
4785 /*    clock_variance                        Variance of PTP master clock  */
4786 /*    grandmaster_identity                  Identity of grandmaster clock */
4787 /*    grandmaster_identity_length           Length of grandmaster Identity*/
4788 /*    steps_removed                         Steps removed from PTP header */
4789 /*    time_source                           The source of timer used by   */
4790 /*                                            grandmaster clock           */
4791 /*                                                                        */
4792 /*  OUTPUT                                                                */
4793 /*                                                                        */
4794 /*    status                                Completion status             */
4795 /*                                                                        */
4796 /*  CALLS                                                                 */
4797 /*                                                                        */
4798 /*    _nx_ptp_client_master_info_get        Actual master info get service*/
4799 /*                                                                        */
4800 /*  CALLED BY                                                             */
4801 /*                                                                        */
4802 /*    Application                                                         */
4803 /*                                                                        */
4804 /*  RELEASE HISTORY                                                       */
4805 /*                                                                        */
4806 /*    DATE              NAME                      DESCRIPTION             */
4807 /*                                                                        */
4808 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4809 /*                                                                        */
4810 /**************************************************************************/
4811 UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
4812                                      UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
4813                                      UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
4814                                      UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
4815 {
4816     if (master_ptr == NX_NULL)
4817     {
4818 
4819         /* Return error status.  */
4820         return(NX_PTR_ERROR);
4821     }
4822 
4823     /* Check for appropriate caller.  */
4824     NX_THREADS_ONLY_CALLER_CHECKING
4825 
4826     return(_nx_ptp_client_master_info_get(master_ptr, address, port_identity, port_identity_length, priority1,
4827                                           priority2, clock_class, clock_accuracy, clock_variance, grandmaster_identity,
4828                                           grandmaster_identity_length, steps_removed, time_source));
4829 }
4830 
4831 
4832 /**************************************************************************/
4833 /*                                                                        */
4834 /*  FUNCTION                                               RELEASE        */
4835 /*                                                                        */
4836 /*    _nx_ptp_client_master_info_get                      PORTABLE C      */
4837 /*                                                           6.1.3        */
4838 /*  AUTHOR                                                                */
4839 /*                                                                        */
4840 /*    Yuxin Zhou, Microsoft Corporation                                   */
4841 /*                                                                        */
4842 /*  DESCRIPTION                                                           */
4843 /*                                                                        */
4844 /*    This function gets information of master clock.                     */
4845 /*                                                                        */
4846 /*  INPUT                                                                 */
4847 /*                                                                        */
4848 /*    master_ptr                            Pointer to PTP master clock   */
4849 /*    address                               Address of master clock       */
4850 /*    port_identity                         PTP master port and identity  */
4851 /*    port_identity_length                  Length of PTP master port and */
4852 /*                                            identity                    */
4853 /*    priority1                             Priority1 of PTP master clock */
4854 /*    priority2                             Priority2 of PTP master clock */
4855 /*    clock_class                           Class of PTP master clock     */
4856 /*    clock_accuracy                        Accuracy of PTP master clock  */
4857 /*    clock_variance                        Variance of PTP master clock  */
4858 /*    grandmaster_identity                  Identity of grandmaster clock */
4859 /*    grandmaster_identity_length           Length of grandmaster Identity*/
4860 /*    steps_removed                         Steps removed from PTP header */
4861 /*    time_source                           The source of timer used by   */
4862 /*                                            grandmaster clock           */
4863 /*                                                                        */
4864 /*  OUTPUT                                                                */
4865 /*                                                                        */
4866 /*    status                                Completion status             */
4867 /*                                                                        */
4868 /*  CALLS                                                                 */
4869 /*                                                                        */
4870 /*    None                                                                */
4871 /*                                                                        */
4872 /*  CALLED BY                                                             */
4873 /*                                                                        */
4874 /*    Application                                                         */
4875 /*                                                                        */
4876 /*  RELEASE HISTORY                                                       */
4877 /*                                                                        */
4878 /*    DATE              NAME                      DESCRIPTION             */
4879 /*                                                                        */
4880 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4881 /*                                                                        */
4882 /**************************************************************************/
4883 UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
4884                                     UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
4885                                     UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
4886                                     UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
4887 {
4888 
4889     /* Set master information when the output pointer is provided.  */
4890     if (address)
4891     {
4892         *address = *(master_ptr -> nx_ptp_client_master_address);
4893     }
4894 
4895     if (port_identity && port_identity_length)
4896     {
4897         *port_identity = master_ptr -> nx_ptp_client_master_port_identity;
4898         *port_identity_length = NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
4899     }
4900 
4901     if (priority1)
4902     {
4903         *priority1 = master_ptr -> nx_ptp_client_master_priority1;
4904     }
4905 
4906     if (priority2)
4907     {
4908         *priority2 = master_ptr -> nx_ptp_client_master_priority2;
4909     }
4910 
4911     if (clock_class)
4912     {
4913         *clock_class = master_ptr -> nx_ptp_client_master_clock_class;
4914     }
4915 
4916     if (clock_accuracy)
4917     {
4918         *clock_accuracy = master_ptr -> nx_ptp_client_master_clock_accuracy;
4919     }
4920 
4921     if (clock_variance)
4922     {
4923         *clock_variance = master_ptr -> nx_ptp_client_master_offset_scaled_log_variance;
4924     }
4925 
4926     if (grandmaster_identity && grandmaster_identity_length)
4927     {
4928         *grandmaster_identity = master_ptr -> nx_ptp_client_master_grandmaster_identity;
4929         *grandmaster_identity_length = NX_PTP_CLOCK_IDENTITY_SIZE;
4930     }
4931 
4932     if (steps_removed)
4933     {
4934         *steps_removed = master_ptr -> nx_ptp_client_master_steps_removed;
4935     }
4936 
4937     if (time_source)
4938     {
4939         *time_source = master_ptr -> nx_ptp_client_master_time_source;
4940     }
4941 
4942     return(NX_SUCCESS);
4943 }
4944 
4945 
4946 /**************************************************************************/
4947 /*                                                                        */
4948 /*  FUNCTION                                               RELEASE        */
4949 /*                                                                        */
4950 /*    _nxe_ptp_client_sync_info_get                       PORTABLE C      */
4951 /*                                                           6.1.3        */
4952 /*  AUTHOR                                                                */
4953 /*                                                                        */
4954 /*    Yuxin Zhou, Microsoft Corporation                                   */
4955 /*                                                                        */
4956 /*  DESCRIPTION                                                           */
4957 /*                                                                        */
4958 /*    This function checks for errors on the PTP Sync get service.        */
4959 /*                                                                        */
4960 /*  INPUT                                                                 */
4961 /*                                                                        */
4962 /*    client_ptr                            Pointer to PTP client         */
4963 /*    flags                                 Flags in Sync message         */
4964 /*    utc_offset                            Offset between TAI and UTC    */
4965 /*                                                                        */
4966 /*  OUTPUT                                                                */
4967 /*                                                                        */
4968 /*    status                                Completion status             */
4969 /*                                                                        */
4970 /*  CALLS                                                                 */
4971 /*                                                                        */
4972 /*    _nx_ptp_client_sync_info_get          Actual Sync info get service  */
4973 /*                                                                        */
4974 /*  CALLED BY                                                             */
4975 /*                                                                        */
4976 /*    Application                                                         */
4977 /*                                                                        */
4978 /*  RELEASE HISTORY                                                       */
4979 /*                                                                        */
4980 /*    DATE              NAME                      DESCRIPTION             */
4981 /*                                                                        */
4982 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
4983 /*                                                                        */
4984 /**************************************************************************/
4985 UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
4986 {
4987     if (sync_ptr == NX_NULL)
4988     {
4989 
4990         /* Return error status.  */
4991         return(NX_PTR_ERROR);
4992     }
4993 
4994     /* Check for appropriate caller.  */
4995     NX_THREADS_ONLY_CALLER_CHECKING
4996 
4997     return(_nx_ptp_client_sync_info_get(sync_ptr, flags, utc_offset));
4998 }
4999 
5000 
5001 /**************************************************************************/
5002 /*                                                                        */
5003 /*  FUNCTION                                               RELEASE        */
5004 /*                                                                        */
5005 /*    _nx_ptp_client_sync_info_get                        PORTABLE C      */
5006 /*                                                           6.1.3        */
5007 /*  AUTHOR                                                                */
5008 /*                                                                        */
5009 /*    Yuxin Zhou, Microsoft Corporation                                   */
5010 /*                                                                        */
5011 /*  DESCRIPTION                                                           */
5012 /*                                                                        */
5013 /*    This function gets information of Sync message.                     */
5014 /*                                                                        */
5015 /*  INPUT                                                                 */
5016 /*                                                                        */
5017 /*    client_ptr                            Pointer to PTP client         */
5018 /*    flags                                 Flags in Sync message         */
5019 /*    utc_offset                            Offset between TAI and UTC    */
5020 /*                                                                        */
5021 /*  OUTPUT                                                                */
5022 /*                                                                        */
5023 /*    status                                Completion status             */
5024 /*                                                                        */
5025 /*  CALLS                                                                 */
5026 /*                                                                        */
5027 /*    None                                                                */
5028 /*                                                                        */
5029 /*  CALLED BY                                                             */
5030 /*                                                                        */
5031 /*    Application                                                         */
5032 /*                                                                        */
5033 /*  RELEASE HISTORY                                                       */
5034 /*                                                                        */
5035 /*    DATE              NAME                      DESCRIPTION             */
5036 /*                                                                        */
5037 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5038 /*                                                                        */
5039 /**************************************************************************/
5040 UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
5041 {
5042 
5043     /* Set SYNC information when the output pointer is provided.  */
5044     if (flags)
5045     {
5046         *flags = sync_ptr -> nx_ptp_client_sync_flags;
5047     }
5048 
5049     if (utc_offset)
5050     {
5051         *utc_offset = sync_ptr -> nx_ptp_client_sync_utc_offset;
5052     }
5053 
5054     return(NX_SUCCESS);
5055 }
5056 
5057 
5058 /**************************************************************************/
5059 /*                                                                        */
5060 /*  FUNCTION                                               RELEASE        */
5061 /*                                                                        */
5062 /*    _nx_ptp_client_packet_timestamp_notify              PORTABLE C      */
5063 /*                                                           6.4.0        */
5064 /*  AUTHOR                                                                */
5065 /*                                                                        */
5066 /*    Yuxin Zhou, Microsoft Corporation                                   */
5067 /*                                                                        */
5068 /*  DESCRIPTION                                                           */
5069 /*                                                                        */
5070 /*    This function notifies the PTP packet is transmitted with timestamp.*/
5071 /*                                                                        */
5072 /*  INPUT                                                                 */
5073 /*                                                                        */
5074 /*    client_ptr                            Pointer to PTP client         */
5075 /*    packet_ptr                            Pointer to PTP packet         */
5076 /*    timestamp_ptr                         Pointer to timestamp          */
5077 /*                                                                        */
5078 /*  OUTPUT                                                                */
5079 /*                                                                        */
5080 /*    None                                                                */
5081 /*                                                                        */
5082 /*  CALLS                                                                 */
5083 /*                                                                        */
5084 /*    None                                                                */
5085 /*                                                                        */
5086 /*  CALLED BY                                                             */
5087 /*                                                                        */
5088 /*    Application                                                         */
5089 /*                                                                        */
5090 /*  RELEASE HISTORY                                                       */
5091 /*                                                                        */
5092 /*    DATE              NAME                      DESCRIPTION             */
5093 /*                                                                        */
5094 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5095 /*  12-31-2023     Tiejun Zhou              Modified comment(s), and      */
5096 /*                                            supported gPTP profile,     */
5097 /*                                            supported master clock,     */
5098 /*                                            resulting in version 6.4.0  */
5099 /*                                                                        */
5100 /**************************************************************************/
5101 VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr)
5102 {
5103 #ifdef NX_ENABLE_GPTP
5104     /* process t1 send time */
5105     if (client_ptr &&
5106         (client_ptr -> nx_ptp_client_pdelay_initiator_state == NX_PTP_CLIENT_PDELAY_WAIT_REQ_TS) &&
5107         (client_ptr -> nx_ptp_client_pdelay_req_packet_ptr == packet_ptr))
5108     {
5109 
5110         /* store timestamp */
5111         client_ptr -> nx_ptp_client_pdelay_req_ts = *timestamp_ptr;
5112 
5113         /* update state */
5114         client_ptr -> nx_ptp_client_pdelay_initiator_state = NX_PTP_CLIENT_PDELAY_WAIT_RESP;
5115     }
5116 
5117     /* process t3 response time */
5118     if (client_ptr &&
5119         (client_ptr -> nx_ptp_client_pdelay_resp_packet_ptr == packet_ptr))
5120     {
5121 
5122         /* store timestamp */
5123         client_ptr -> nx_ptp_client_pdelay_resp_origin = *timestamp_ptr;
5124 
5125          /* set timer event */
5126         tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_PDELAY_FOLLOW_EVENT, TX_OR);
5127 
5128         client_ptr -> nx_ptp_client_pdelay_resp_packet_ptr = NX_NULL;
5129     }
5130 
5131 
5132 
5133 #endif /* NX_ENABLE_GPTP */
5134 
5135     /* get timestamp of previous delay_req message */
5136     if (client_ptr &&
5137         (client_ptr -> nx_ptp_client_delay_state == NX_PTP_CLIENT_DELAY_WAIT_REQ_TS) &&
5138         (client_ptr -> nx_ptp_client_delay_req_packet_ptr == packet_ptr))
5139     {
5140 
5141         /* store timestamp */
5142         client_ptr -> nx_ptp_client_delay_ts = *timestamp_ptr;
5143 
5144         /* update state */
5145         client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_RESP;
5146     }
5147 
5148 #if defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC)
5149     /* get timestamp of previous sync message */
5150     if (client_ptr && (client_ptr -> nx_ptp_client_sync_packet_ptr == packet_ptr))
5151     {
5152 
5153         client_ptr -> nx_ptp_client_sync_packet_ptr = NX_NULL;
5154 
5155         /* store timestamp */
5156         client_ptr -> nx_ptp_client_sync_ts_local = *timestamp_ptr;
5157 
5158          /* set follow up event */
5159         tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_SYNC_FOLLOW_EVENT, TX_OR);
5160     }
5161 #endif /* defined(NX_PTP_ENABLE_MASTER) || defined(NX_PTP_ENABLE_REVERSE_SYNC) */
5162 }
5163 
5164 
5165 /**************************************************************************/
5166 /*                                                                        */
5167 /*  FUNCTION                                               RELEASE        */
5168 /*                                                                        */
5169 /*    _nx_ptp_client_soft_clock_callback                  PORTABLE C      */
5170 /*                                                           6.1.3        */
5171 /*  AUTHOR                                                                */
5172 /*                                                                        */
5173 /*    Yuxin Zhou, Microsoft Corporation                                   */
5174 /*                                                                        */
5175 /*  DESCRIPTION                                                           */
5176 /*                                                                        */
5177 /*    This function implements soft PTP clock.                            */
5178 /*                                                                        */
5179 /*  INPUT                                                                 */
5180 /*                                                                        */
5181 /*    client_ptr                            Pointer to PTP client         */
5182 /*    operation                             PTP clock operation           */
5183 /*    time_ptr                              Pointer to timestamp          */
5184 /*    packet_ptr                            Pointer to PTP packet         */
5185 /*    callback_data                         Pointer to callback data      */
5186 /*                                                                        */
5187 /*  OUTPUT                                                                */
5188 /*                                                                        */
5189 /*    status                                Completion status             */
5190 /*                                                                        */
5191 /*  CALLS                                                                 */
5192 /*                                                                        */
5193 /*    _nx_ptp_client_soft_clock_adjust      Adjust soft PTP clock         */
5194 /*    _nx_ptp_client_utility_inc64          Increment a 64-bit number     */
5195 /*                                                                        */
5196 /*  CALLED BY                                                             */
5197 /*                                                                        */
5198 /*    PTP internal                                                        */
5199 /*                                                                        */
5200 /*  RELEASE HISTORY                                                       */
5201 /*                                                                        */
5202 /*    DATE              NAME                      DESCRIPTION             */
5203 /*                                                                        */
5204 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5205 /*                                                                        */
5206 /**************************************************************************/
5207 UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation,
5208                                         NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
5209                                         VOID *callback_data)
5210 {
5211 TX_INTERRUPT_SAVE_AREA
5212 
5213     NX_PARAMETER_NOT_USED(callback_data);
5214 
5215     switch (operation)
5216     {
5217 
5218     /* Nothing to do for soft initialization.  */
5219     case NX_PTP_CLIENT_CLOCK_INIT:
5220         break;
5221 
5222     /* Set clock.  */
5223     case NX_PTP_CLIENT_CLOCK_SET:
5224         TX_DISABLE
5225         client_ptr -> nx_ptp_client_soft_clock = *time_ptr;
5226         TX_RESTORE
5227         break;
5228 
5229     /* Extract timestamp from packet.
5230        For soft implementation, simply fallthrough and return current timestamp.  */
5231     case NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT:
5232 
5233     /* Get clock.  */
5234     case NX_PTP_CLIENT_CLOCK_GET:
5235         TX_DISABLE
5236         *time_ptr = client_ptr -> nx_ptp_client_soft_clock;
5237         TX_RESTORE
5238         break;
5239 
5240     /* Adjust clock.  */
5241     case NX_PTP_CLIENT_CLOCK_ADJUST:
5242         _nx_ptp_client_soft_clock_adjust(client_ptr, time_ptr -> nanosecond);
5243         break;
5244 
5245     /* Prepare timestamp for current packet.
5246        For soft implementation, simply notify current timestamp.  */
5247     case NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE:
5248         _nx_ptp_client_packet_timestamp_notify(client_ptr, packet_ptr, &(client_ptr -> nx_ptp_client_soft_clock));
5249         break;
5250 
5251     /* Update soft timer.  */
5252     case NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE:
5253         TX_DISABLE
5254 
5255         /* increment the nanosecond field of the software clock */
5256         time_ptr -> nanosecond +=
5257             (LONG)(NX_PTP_NANOSECONDS_PER_SEC / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND);
5258 
5259         /* update the second field */
5260         if (time_ptr -> nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
5261         {
5262             time_ptr -> nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
5263             _nx_ptp_client_utility_inc64(&(time_ptr -> second_high),
5264                                          &(time_ptr -> second_low));
5265         }
5266         TX_RESTORE
5267         break;
5268 
5269     default:
5270         return(NX_PTP_PARAM_ERROR);
5271     }
5272 
5273     return(NX_SUCCESS);
5274 }
5275 
5276 
5277 /**************************************************************************/
5278 /*                                                                        */
5279 /*  FUNCTION                                               RELEASE        */
5280 /*                                                                        */
5281 /*    _nxe_ptp_client_utility_time_diff                   PORTABLE C      */
5282 /*                                                           6.1.3        */
5283 /*  AUTHOR                                                                */
5284 /*                                                                        */
5285 /*    Yuxin Zhou, Microsoft Corporation                                   */
5286 /*                                                                        */
5287 /*  DESCRIPTION                                                           */
5288 /*                                                                        */
5289 /*    This function checks for errors on the PTP time difference service. */
5290 /*                                                                        */
5291 /*  INPUT                                                                 */
5292 /*                                                                        */
5293 /*    time1_ptr                             Pointer to first PTP time     */
5294 /*    time2_ptr                             Pointer to second PTP time    */
5295 /*    result_ptr                            Pointer to result time1-time2 */
5296 /*                                                                        */
5297 /*  OUTPUT                                                                */
5298 /*                                                                        */
5299 /*    status                                Completion status             */
5300 /*                                                                        */
5301 /*  CALLS                                                                 */
5302 /*                                                                        */
5303 /*    _nx_ptp_client_utility_time_diff      Actual time difference service*/
5304 /*                                                                        */
5305 /*  CALLED BY                                                             */
5306 /*                                                                        */
5307 /*    Application                                                         */
5308 /*                                                                        */
5309 /*  RELEASE HISTORY                                                       */
5310 /*                                                                        */
5311 /*    DATE              NAME                      DESCRIPTION             */
5312 /*                                                                        */
5313 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5314 /*                                                                        */
5315 /**************************************************************************/
5316 UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
5317 {
5318 
5319     /* Check input parameters.  */
5320     if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL))
5321     {
5322 
5323         /* Return error status.  */
5324         return(NX_PTR_ERROR);
5325     }
5326 
5327     /* Check for appropriate caller.  */
5328     NX_THREADS_ONLY_CALLER_CHECKING
5329 
5330     /* Call the actual function.  */
5331     return(_nx_ptp_client_utility_time_diff(time1_ptr, time2_ptr, result_ptr));
5332 }
5333 
5334 /**************************************************************************/
5335 /*                                                                        */
5336 /*  FUNCTION                                               RELEASE        */
5337 /*                                                                        */
5338 /*    _nxe_ptp_client_utility_time_sum                    PORTABLE C      */
5339 /*                                                           6.4.0        */
5340 /*  AUTHOR                                                                */
5341 /*                                                                        */
5342 /*    Tiejun Zhou, Microsoft Corporation                                  */
5343 /*                                                                        */
5344 /*  DESCRIPTION                                                           */
5345 /*                                                                        */
5346 /*    This function checks for errors on the PTP time sum service.        */
5347 /*                                                                        */
5348 /*  INPUT                                                                 */
5349 /*                                                                        */
5350 /*    time1_ptr                             Pointer to first PTP time     */
5351 /*    time2_ptr                             Pointer to second PTP time    */
5352 /*    result_ptr                            Pointer to result time1+time2 */
5353 /*                                                                        */
5354 /*  OUTPUT                                                                */
5355 /*                                                                        */
5356 /*    status                                Completion status             */
5357 /*                                                                        */
5358 /*  CALLS                                                                 */
5359 /*                                                                        */
5360 /*    _nx_ptp_client_utility_time_sum       Actual time sum service       */
5361 /*                                                                        */
5362 /*  CALLED BY                                                             */
5363 /*                                                                        */
5364 /*    Application                                                         */
5365 /*                                                                        */
5366 /*  RELEASE HISTORY                                                       */
5367 /*                                                                        */
5368 /*    DATE              NAME                      DESCRIPTION             */
5369 /*                                                                        */
5370 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
5371 /*                                                                        */
5372 /**************************************************************************/
5373 UINT _nxe_ptp_client_utility_time_sum(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
5374 {
5375 
5376     /* Check input parameters.  */
5377     if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL))
5378     {
5379 
5380         /* Return error status.  */
5381         return(NX_PTR_ERROR);
5382     }
5383 
5384     /* Check for appropriate caller.  */
5385     NX_THREADS_ONLY_CALLER_CHECKING
5386 
5387     /* Call the actual function.  */
5388     return(_nx_ptp_client_utility_time_sum(time1_ptr, time2_ptr, result_ptr));
5389 }
5390 
5391 
5392 /**************************************************************************/
5393 /*                                                                        */
5394 /*  FUNCTION                                               RELEASE        */
5395 /*                                                                        */
5396 /*    _nx_ptp_client_utility_time_diff                    PORTABLE C      */
5397 /*                                                           6.1.3        */
5398 /*  AUTHOR                                                                */
5399 /*                                                                        */
5400 /*    Yuxin Zhou, Microsoft Corporation                                   */
5401 /*                                                                        */
5402 /*  DESCRIPTION                                                           */
5403 /*                                                                        */
5404 /*    This function computes the difference between two PTP times.        */
5405 /*                                                                        */
5406 /*  INPUT                                                                 */
5407 /*                                                                        */
5408 /*    time1_ptr                             Pointer to first PTP time     */
5409 /*    time2_ptr                             Pointer to second PTP time    */
5410 /*    result_ptr                            Pointer to result time1-time2 */
5411 /*                                                                        */
5412 /*  OUTPUT                                                                */
5413 /*                                                                        */
5414 /*    status                                Completion status             */
5415 /*                                                                        */
5416 /*  CALLS                                                                 */
5417 /*                                                                        */
5418 /*    _nx_ptp_client_utility_sub64          Subtracts two 64-bit numbers  */
5419 /*    _nx_ptp_client_utility_dec64          Decrement a 64-bit number     */
5420 /*    _nx_ptp_client_utility_inc64          Increment a 64-bit number     */
5421 /*                                                                        */
5422 /*  CALLED BY                                                             */
5423 /*                                                                        */
5424 /*    Application                                                         */
5425 /*    _nx_ptp_client_delay_resp_received    Process delay response        */
5426 /*                                                                        */
5427 /*  RELEASE HISTORY                                                       */
5428 /*                                                                        */
5429 /*    DATE              NAME                      DESCRIPTION             */
5430 /*                                                                        */
5431 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5432 /*                                                                        */
5433 /**************************************************************************/
5434 UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
5435 {
5436 LONG  sec_hi;
5437 ULONG sec_lo;
5438 LONG  ns;
5439 
5440     /* compute difference of seconds */
5441     sec_hi = time1_ptr -> second_high;
5442     sec_lo = time1_ptr -> second_low;
5443     _nx_ptp_client_utility_sub64(&sec_hi, &sec_lo, time2_ptr -> second_high,
5444                                  time2_ptr -> second_low);
5445 
5446     /* compute difference of nanoseconds */
5447     /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */
5448     ns = time1_ptr -> nanosecond - time2_ptr -> nanosecond;
5449 
5450     /* keep nanoseconds in range +/-0-999999999 */
5451     if (ns <= -NX_PTP_NANOSECONDS_PER_SEC)
5452     {
5453         ns += NX_PTP_NANOSECONDS_PER_SEC;
5454         _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
5455     }
5456     else if (ns >= NX_PTP_NANOSECONDS_PER_SEC)
5457     {
5458         ns -= NX_PTP_NANOSECONDS_PER_SEC;
5459         _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
5460     }
5461 
5462     /* ensure the nanoseconds field has same sign as seconds field */
5463     if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0)))
5464     {
5465         /* positive number of seconds */
5466         if (ns < 0)
5467         {
5468             ns += NX_PTP_NANOSECONDS_PER_SEC;
5469             _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
5470         }
5471     }
5472     else if (sec_hi < 0)
5473     {
5474         /* negative number of seconds */
5475         if (ns > 0)
5476         {
5477             ns -= NX_PTP_NANOSECONDS_PER_SEC;
5478             _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
5479         }
5480     }
5481 
5482     /* return result time */
5483     result_ptr -> second_high = sec_hi;
5484     result_ptr -> second_low  = sec_lo;
5485     result_ptr -> nanosecond  = ns;
5486 
5487     return(NX_SUCCESS);
5488 }
5489 
5490 
5491 /**************************************************************************/
5492 /*                                                                        */
5493 /*  FUNCTION                                               RELEASE        */
5494 /*                                                                        */
5495 /*    _nx_ptp_client_utility_time_sum                    PORTABLE C       */
5496 /*                                                           6.4.0        */
5497 /*  AUTHOR                                                                */
5498 /*                                                                        */
5499 /*    Tiejun Zhou, Microsoft Corporation                                  */
5500 /*                                                                        */
5501 /*  DESCRIPTION                                                           */
5502 /*                                                                        */
5503 /*    This function computes the sum of two PTP times.                    */
5504 /*                                                                        */
5505 /*  INPUT                                                                 */
5506 /*                                                                        */
5507 /*    time1_ptr                             Pointer to first PTP time     */
5508 /*    time2_ptr                             Pointer to second PTP time    */
5509 /*    result_ptr                            Pointer to result time1+time2 */
5510 /*                                                                        */
5511 /*  OUTPUT                                                                */
5512 /*                                                                        */
5513 /*    status                                Completion status             */
5514 /*                                                                        */
5515 /*  CALLS                                                                 */
5516 /*                                                                        */
5517 /*    _nx_ptp_client_utility_add64          Adds two 64-bit numbers       */
5518 /*    _nx_ptp_client_utility_dec64          Decrement a 64-bit number     */
5519 /*    _nx_ptp_client_utility_inc64          Increment a 64-bit number     */
5520 /*                                                                        */
5521 /*  CALLED BY                                                             */
5522 /*                                                                        */
5523 /*    Application                                                         */
5524 /*    _nx_ptp_client_pdelay_resp_received   Process pdelay response       */
5525 /*                                                                        */
5526 /*  RELEASE HISTORY                                                       */
5527 /*                                                                        */
5528 /*    DATE              NAME                      DESCRIPTION             */
5529 /*                                                                        */
5530 /*  12-31-2023     Tiejun Zhou              Initial Version 6.4.0         */
5531 /*                                                                        */
5532 /**************************************************************************/
5533 UINT _nx_ptp_client_utility_time_sum(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
5534 {
5535 LONG  sec_hi;
5536 ULONG sec_lo;
5537 LONG  ns;
5538 
5539     /* compute sum of seconds */
5540     sec_hi = time1_ptr -> second_high;
5541     sec_lo = time1_ptr -> second_low;
5542     _nx_ptp_client_utility_add64(&sec_hi, &sec_lo, time2_ptr -> second_high,
5543                                  time2_ptr -> second_low);
5544 
5545     /* compute sum of nanoseconds */
5546     /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */
5547     ns = time1_ptr -> nanosecond + time2_ptr -> nanosecond;
5548 
5549     /* keep nanoseconds in range +/-0-999999999 */
5550     if (ns <= -NX_PTP_NANOSECONDS_PER_SEC)
5551     {
5552         ns += NX_PTP_NANOSECONDS_PER_SEC;
5553         _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
5554     }
5555     else if (ns >= NX_PTP_NANOSECONDS_PER_SEC)
5556     {
5557         ns -= NX_PTP_NANOSECONDS_PER_SEC;
5558         _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
5559     }
5560 
5561     /* ensure the nanoseconds field has same sign as seconds field */
5562     if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0)))
5563     {
5564         /* positive number of seconds */
5565         if (ns < 0)
5566         {
5567             ns += NX_PTP_NANOSECONDS_PER_SEC;
5568             _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
5569         }
5570     }
5571     else if (sec_hi < 0)
5572     {
5573         /* negative number of seconds */
5574         if (ns > 0)
5575         {
5576             ns -= NX_PTP_NANOSECONDS_PER_SEC;
5577             _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
5578         }
5579     }
5580 
5581     /* return result time */
5582     result_ptr -> second_high = sec_hi;
5583     result_ptr -> second_low  = sec_lo;
5584     result_ptr -> nanosecond  = ns;
5585 
5586     return(NX_SUCCESS);
5587 }
5588 
5589 /**************************************************************************/
5590 /*                                                                        */
5591 /*  FUNCTION                                               RELEASE        */
5592 /*                                                                        */
5593 /*    _nxe_ptp_client_utility_convert_time_to_date        PORTABLE C      */
5594 /*                                                           6.1.3        */
5595 /*  AUTHOR                                                                */
5596 /*                                                                        */
5597 /*    Yuxin Zhou, Microsoft Corporation                                   */
5598 /*                                                                        */
5599 /*  DESCRIPTION                                                           */
5600 /*                                                                        */
5601 /*    This function checks for errors on the PTP time conversion service. */
5602 /*                                                                        */
5603 /*  INPUT                                                                 */
5604 /*                                                                        */
5605 /*    time_ptr                              Pointer to PTP time           */
5606 /*    offset                                signed second offset to add   */
5607 /*                                          the PTP time                  */
5608 /*    date_time_ptr                         Pointer to resulting date     */
5609 /*                                                                        */
5610 /*  OUTPUT                                                                */
5611 /*                                                                        */
5612 /*    status                                Completion status             */
5613 /*                                                                        */
5614 /*  CALLS                                                                 */
5615 /*                                                                        */
5616 /*    _nx_ptp_client_utility_convert_time_to_date                         */
5617 /*                                          Actual time conversion service*/
5618 /*                                                                        */
5619 /*  CALLED BY                                                             */
5620 /*                                                                        */
5621 /*    Application                                                         */
5622 /*                                                                        */
5623 /*  RELEASE HISTORY                                                       */
5624 /*                                                                        */
5625 /*    DATE              NAME                      DESCRIPTION             */
5626 /*                                                                        */
5627 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5628 /*                                                                        */
5629 /**************************************************************************/
5630 UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
5631 {
5632 
5633     /* Check input parameters.  */
5634     if ((time_ptr == NX_NULL) || (date_time_ptr == NX_NULL))
5635     {
5636 
5637         /* Return error status.  */
5638         return(NX_PTR_ERROR);
5639     }
5640 
5641     /* Check for appropriate caller.  */
5642     NX_THREADS_ONLY_CALLER_CHECKING
5643 
5644     /* Call the actual function.  */
5645     return(_nx_ptp_client_utility_convert_time_to_date(time_ptr, offset, date_time_ptr));
5646 }
5647 
5648 
5649 /**************************************************************************/
5650 /*                                                                        */
5651 /*  FUNCTION                                               RELEASE        */
5652 /*                                                                        */
5653 /*    _nx_ptp_client_utility_convert_time_to_date         PORTABLE C      */
5654 /*                                                           6.1.3        */
5655 /*  AUTHOR                                                                */
5656 /*                                                                        */
5657 /*    Yuxin Zhou, Microsoft Corporation                                   */
5658 /*                                                                        */
5659 /*  DESCRIPTION                                                           */
5660 /*                                                                        */
5661 /*    This function converts a PTP time to a UTC date and time.           */
5662 /*                                                                        */
5663 /*  INPUT                                                                 */
5664 /*                                                                        */
5665 /*    time_ptr                              Pointer to PTP time           */
5666 /*    offset                                Signed second offset to add   */
5667 /*                                          the PTP time                  */
5668 /*    date_time_ptr                         Pointer to resulting date     */
5669 /*                                                                        */
5670 /*  OUTPUT                                                                */
5671 /*                                                                        */
5672 /*    status                                Completion status             */
5673 /*                                                                        */
5674 /*  CALLS                                                                 */
5675 /*                                                                        */
5676 /*    _nx_ptp_client_utility_add64          Add two 64-bit number         */
5677 /*                                                                        */
5678 /*  CALLED BY                                                             */
5679 /*                                                                        */
5680 /*    Application                                                         */
5681 /*                                                                        */
5682 /*  RELEASE HISTORY                                                       */
5683 /*                                                                        */
5684 /*    DATE              NAME                      DESCRIPTION             */
5685 /*                                                                        */
5686 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5687 /*                                                                        */
5688 /**************************************************************************/
5689 UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
5690 {
5691 #define IS_LEAP(y)      (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
5692 #define SECS_PER_MINUTE 60
5693 #define SECS_PER_HOUR   (60 * SECS_PER_MINUTE)
5694 #define SECS_PER_DAY    (24 * SECS_PER_HOUR)
5695 LONG  secs_high;
5696 ULONG secs_low;
5697 UINT  year, month, day, hour, minute;
5698 ULONG secs_per_year, secs_per_month;
5699 ULONG weekday;
5700 UINT  is_leap;
5701 
5702     /* get number of seconds */
5703     secs_high = time_ptr -> second_high;
5704     secs_low  = time_ptr -> second_low;
5705 
5706     /* add local time offset */
5707     if (offset != 0)
5708     {
5709         _nx_ptp_client_utility_add64(&secs_high, &secs_low, offset < 0 ? -1 : 0, (ULONG)offset);
5710     }
5711     if (secs_high < 0)
5712     {
5713 
5714         /* invalid negative time */
5715         return(NX_PTP_PARAM_ERROR);
5716     }
5717 
5718     /* determine the current year from Epoch (January 1, 1970) */
5719     year = 1970;
5720     secs_per_year = 365 * SECS_PER_DAY;
5721     is_leap = 0;
5722     weekday = 4;  /* thursday */
5723     while ((secs_high > 0) || (secs_low >= secs_per_year))
5724     {
5725         if (secs_low < secs_per_year)
5726         {
5727             secs_high--;
5728         }
5729         secs_low -= secs_per_year;
5730         weekday += is_leap ? 366 : 365;
5731         year++;
5732         is_leap = IS_LEAP(year) ? 1 : 0;
5733         secs_per_year = is_leap ? 366 * SECS_PER_DAY : 365 * SECS_PER_DAY;
5734     }
5735     /* compute day of the week from remaining seconds */
5736     weekday = (weekday + secs_low / SECS_PER_DAY) % 7;
5737 
5738     /* determine current month */
5739     month = 1;
5740     secs_per_month = 31 * SECS_PER_DAY;
5741     while (secs_low >= secs_per_month)
5742     {
5743         secs_low -= secs_per_month;
5744         month++;
5745         if (month == 2)
5746         {
5747 
5748             /* february */
5749             secs_per_month = is_leap ? 29 * SECS_PER_DAY : 28 * SECS_PER_DAY;
5750         }
5751         else if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
5752         {
5753 
5754             /* april, june, september, november */
5755             secs_per_month = 30 * SECS_PER_DAY;
5756         }
5757         else
5758         {
5759 
5760             /* the other months */
5761             secs_per_month = 31 * SECS_PER_DAY;
5762         }
5763     }
5764 
5765     /* determine current day of the month */
5766     day = secs_low / SECS_PER_DAY;
5767     secs_low -= day * SECS_PER_DAY;
5768 
5769     /* determine current hour */
5770     hour = secs_low / SECS_PER_HOUR;
5771     secs_low -= hour * SECS_PER_HOUR;
5772 
5773     /* determine current minute */
5774     minute = secs_low / SECS_PER_MINUTE;
5775     secs_low -= minute * SECS_PER_MINUTE;
5776 
5777     /* return date */
5778     date_time_ptr -> year         = year;
5779     date_time_ptr -> month        = (UCHAR)month;
5780     date_time_ptr -> day          = (UCHAR)(day + 1);
5781     date_time_ptr -> hour         = (UCHAR)hour;
5782     date_time_ptr -> minute       = (UCHAR)minute;
5783     date_time_ptr -> second       = (UCHAR)secs_low;
5784     date_time_ptr -> weekday      = (UCHAR)weekday;
5785     date_time_ptr -> nanosecond   = (ULONG)time_ptr -> nanosecond;
5786 
5787     return(NX_SUCCESS);
5788 }
5789 
5790 
5791 /**************************************************************************/
5792 /*                                                                        */
5793 /*  FUNCTION                                               RELEASE        */
5794 /*                                                                        */
5795 /*    _nx_ptp_client_utility_add64                        PORTABLE C      */
5796 /*                                                           6.1.3        */
5797 /*  AUTHOR                                                                */
5798 /*                                                                        */
5799 /*    Yuxin Zhou, Microsoft Corporation                                   */
5800 /*                                                                        */
5801 /*  DESCRIPTION                                                           */
5802 /*                                                                        */
5803 /*    This function adds two 64-bit numbers: A = A + B.                   */
5804 /*                                                                        */
5805 /*  INPUT                                                                 */
5806 /*                                                                        */
5807 /*    a_hi                                  Pointer to higher 32-bit of A */
5808 /*    a_lo                                  Pointer to lower 32-bit of A  */
5809 /*    b_hi                                  higher 32-bit of B            */
5810 /*    b_lo                                  lower 32-bit of B             */
5811 /*                                                                        */
5812 /*  OUTPUT                                                                */
5813 /*                                                                        */
5814 /*    None                                                                */
5815 /*                                                                        */
5816 /*  CALLS                                                                 */
5817 /*                                                                        */
5818 /*    None                                                                */
5819 /*                                                                        */
5820 /*  CALLED BY                                                             */
5821 /*                                                                        */
5822 /*    _nx_ptp_client_clock_adjust           Adjust PTP clock              */
5823 /*    _nx_ptp_client_utility_convert_time_to_date                         */
5824 /*                                          Convert time to date          */
5825 /*                                                                        */
5826 /*  RELEASE HISTORY                                                       */
5827 /*                                                                        */
5828 /*    DATE              NAME                      DESCRIPTION             */
5829 /*                                                                        */
5830 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5831 /*                                                                        */
5832 /**************************************************************************/
5833 VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
5834 {
5835 LONG  r_hi;
5836 ULONG r_lo;
5837 
5838     r_hi = *a_hi + b_hi;
5839     r_lo = *a_lo + b_lo;
5840     if ((r_lo < *a_lo) || (r_lo < b_lo))
5841     {
5842         r_hi++;     /* add carry */
5843     }
5844     *a_hi = r_hi;
5845     *a_lo = r_lo;
5846 }
5847 
5848 
5849 /**************************************************************************/
5850 /*                                                                        */
5851 /*  FUNCTION                                               RELEASE        */
5852 /*                                                                        */
5853 /*    _nx_ptp_client_utility_sub64                        PORTABLE C      */
5854 /*                                                           6.1.3        */
5855 /*  AUTHOR                                                                */
5856 /*                                                                        */
5857 /*    Yuxin Zhou, Microsoft Corporation                                   */
5858 /*                                                                        */
5859 /*  DESCRIPTION                                                           */
5860 /*                                                                        */
5861 /*    This function substracts two 64-bit numbers: A = A - B.             */
5862 /*                                                                        */
5863 /*  INPUT                                                                 */
5864 /*                                                                        */
5865 /*    a_hi                                  Pointer to higher 32-bit of A */
5866 /*    a_lo                                  Pointer to lower 32-bit of A  */
5867 /*    b_hi                                  higher 32-bit of B            */
5868 /*    b_lo                                  lower 32-bit of B             */
5869 /*                                                                        */
5870 /*  OUTPUT                                                                */
5871 /*                                                                        */
5872 /*    None                                                                */
5873 /*                                                                        */
5874 /*  CALLS                                                                 */
5875 /*                                                                        */
5876 /*    None                                                                */
5877 /*                                                                        */
5878 /*  CALLED BY                                                             */
5879 /*                                                                        */
5880 /*    _nx_ptp_client_utility_time_diff      Diff two PTP times            */
5881 /*                                                                        */
5882 /*  RELEASE HISTORY                                                       */
5883 /*                                                                        */
5884 /*    DATE              NAME                      DESCRIPTION             */
5885 /*                                                                        */
5886 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5887 /*                                                                        */
5888 /**************************************************************************/
5889 VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
5890 {
5891 LONG  r_hi;
5892 ULONG r_lo;
5893 
5894     r_hi = *a_hi - b_hi;
5895     r_lo = *a_lo - b_lo;
5896     if (*a_lo < b_lo)
5897     {
5898         r_hi--;     /* subtract carry */
5899     }
5900     *a_hi = r_hi;
5901     *a_lo = r_lo;
5902 }
5903 
5904 
5905 /**************************************************************************/
5906 /*                                                                        */
5907 /*  FUNCTION                                               RELEASE        */
5908 /*                                                                        */
5909 /*    _nx_ptp_client_utility_inc64                        PORTABLE C      */
5910 /*                                                           6.1.3        */
5911 /*  AUTHOR                                                                */
5912 /*                                                                        */
5913 /*    Yuxin Zhou, Microsoft Corporation                                   */
5914 /*                                                                        */
5915 /*  DESCRIPTION                                                           */
5916 /*                                                                        */
5917 /*    This function increments a 64-bit number: A = A + 1.                */
5918 /*                                                                        */
5919 /*  INPUT                                                                 */
5920 /*                                                                        */
5921 /*    a_hi                                  Pointer to higher 32-bit of A */
5922 /*    a_lo                                  Pointer to lower 32-bit of A  */
5923 /*                                                                        */
5924 /*  OUTPUT                                                                */
5925 /*                                                                        */
5926 /*    None                                                                */
5927 /*                                                                        */
5928 /*  CALLS                                                                 */
5929 /*                                                                        */
5930 /*    None                                                                */
5931 /*                                                                        */
5932 /*  CALLED BY                                                             */
5933 /*                                                                        */
5934 /*    _nx_ptp_client_soft_clock_adjust      Adjust soft PTP clock         */
5935 /*    _nx_ptp_client_clock_adjust           Adjust PTP clock              */
5936 /*    _nx_ptp_client_utility_time_diff      Diff two PTP times            */
5937 /*    _nx_ptp_client_soft_clock_callback    Soft PTP clock                */
5938 /*                                                                        */
5939 /*  RELEASE HISTORY                                                       */
5940 /*                                                                        */
5941 /*    DATE              NAME                      DESCRIPTION             */
5942 /*                                                                        */
5943 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5944 /*                                                                        */
5945 /**************************************************************************/
5946 VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo)
5947 {
5948 ULONG r_lo;
5949 
5950     r_lo = *a_lo + 1;
5951     if (r_lo == 0)
5952     {
5953         *a_hi = *a_hi + 1;      /* add carry */
5954     }
5955     *a_lo = r_lo;
5956 }
5957 
5958 
5959 /**************************************************************************/
5960 /*                                                                        */
5961 /*  FUNCTION                                               RELEASE        */
5962 /*                                                                        */
5963 /*    _nx_ptp_client_utility_dec64                        PORTABLE C      */
5964 /*                                                           6.1.3        */
5965 /*  AUTHOR                                                                */
5966 /*                                                                        */
5967 /*    Yuxin Zhou, Microsoft Corporation                                   */
5968 /*                                                                        */
5969 /*  DESCRIPTION                                                           */
5970 /*                                                                        */
5971 /*    This function decrements a 64-bit number: A = A - 1.                */
5972 /*                                                                        */
5973 /*  INPUT                                                                 */
5974 /*                                                                        */
5975 /*    a_hi                                  Pointer to higher 32-bit of A */
5976 /*    a_lo                                  Pointer to lower 32-bit of A  */
5977 /*                                                                        */
5978 /*  OUTPUT                                                                */
5979 /*                                                                        */
5980 /*    None                                                                */
5981 /*                                                                        */
5982 /*  CALLS                                                                 */
5983 /*                                                                        */
5984 /*    None                                                                */
5985 /*                                                                        */
5986 /*  CALLED BY                                                             */
5987 /*                                                                        */
5988 /*    _nx_ptp_client_soft_clock_adjust      Adjust soft PTP clock         */
5989 /*    _nx_ptp_client_clock_adjust           Adjust PTP clock              */
5990 /*    _nx_ptp_client_utility_time_diff      Diff two PTP times            */
5991 /*                                                                        */
5992 /*  RELEASE HISTORY                                                       */
5993 /*                                                                        */
5994 /*    DATE              NAME                      DESCRIPTION             */
5995 /*                                                                        */
5996 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
5997 /*                                                                        */
5998 /**************************************************************************/
5999 VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo)
6000 {
6001 ULONG r_lo;
6002 
6003     r_lo = *a_lo;
6004     if (r_lo == 0)
6005     {
6006         *a_hi = *a_hi - 1;      /* subtract carry */
6007     }
6008     *a_lo = r_lo - 1;
6009 }
6010 
6011 
6012 /**************************************************************************/
6013 /*                                                                        */
6014 /*  FUNCTION                                               RELEASE        */
6015 /*                                                                        */
6016 /*    _nx_ptp_client_utility_neg64                        PORTABLE C      */
6017 /*                                                           6.1.3        */
6018 /*  AUTHOR                                                                */
6019 /*                                                                        */
6020 /*    Yuxin Zhou, Microsoft Corporation                                   */
6021 /*                                                                        */
6022 /*  DESCRIPTION                                                           */
6023 /*                                                                        */
6024 /*    This function changes the sign of a 64-bit number: A = -A.          */
6025 /*                                                                        */
6026 /*  INPUT                                                                 */
6027 /*                                                                        */
6028 /*    a_hi                                  Pointer to higher 32-bit of A */
6029 /*    a_lo                                  Pointer to lower 32-bit of A  */
6030 /*                                                                        */
6031 /*  OUTPUT                                                                */
6032 /*                                                                        */
6033 /*    None                                                                */
6034 /*                                                                        */
6035 /*  CALLS                                                                 */
6036 /*                                                                        */
6037 /*    None                                                                */
6038 /*                                                                        */
6039 /*  CALLED BY                                                             */
6040 /*                                                                        */
6041 /*    _nx_ptp_client_utility_time_div_by_2  Divide a PTP time by 2        */
6042 /*                                                                        */
6043 /*  RELEASE HISTORY                                                       */
6044 /*                                                                        */
6045 /*    DATE              NAME                      DESCRIPTION             */
6046 /*                                                                        */
6047 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
6048 /*                                                                        */
6049 /**************************************************************************/
6050 VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo)
6051 {
6052 LONG r_hi;
6053 
6054     r_hi = -*a_hi;
6055     if (*a_lo != 0)
6056     {
6057         r_hi--;     /* subtract carry */
6058     }
6059     *a_hi = r_hi;
6060     *a_lo = -*a_lo;
6061 }
6062 
6063 
6064 /**************************************************************************/
6065 /*                                                                        */
6066 /*  FUNCTION                                               RELEASE        */
6067 /*                                                                        */
6068 /*    _nx_ptp_client_utility_time_div_by_2                PORTABLE C      */
6069 /*                                                           6.1.3        */
6070 /*  AUTHOR                                                                */
6071 /*                                                                        */
6072 /*    Yuxin Zhou, Microsoft Corporation                                   */
6073 /*                                                                        */
6074 /*  DESCRIPTION                                                           */
6075 /*                                                                        */
6076 /*    This function divides a PTP time by 2.                              */
6077 /*                                                                        */
6078 /*  INPUT                                                                 */
6079 /*                                                                        */
6080 /*    time_ptr                          Pointer to PTP time               */
6081 /*                                                                        */
6082 /*  OUTPUT                                                                */
6083 /*                                                                        */
6084 /*    None                                                                */
6085 /*                                                                        */
6086 /*  CALLS                                                                 */
6087 /*                                                                        */
6088 /*    _nx_ptp_client_utility_neg64          Change the sign of number     */
6089 /*                                                                        */
6090 /*  CALLED BY                                                             */
6091 /*                                                                        */
6092 /*    _nx_ptp_client_delay_resp_received    Process delay response        */
6093 /*                                                                        */
6094 /*  RELEASE HISTORY                                                       */
6095 /*                                                                        */
6096 /*    DATE              NAME                      DESCRIPTION             */
6097 /*                                                                        */
6098 /*  12-31-2020     Yuxin Zhou               Initial Version 6.1.3         */
6099 /*                                                                        */
6100 /**************************************************************************/
6101 VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr)
6102 {
6103 UINT  neg;
6104 LONG  sec_hi;
6105 ULONG sec_lo;
6106 LONG  ns;
6107 
6108     /* get current time value */
6109     sec_hi = time_ptr -> second_high;
6110     sec_lo = time_ptr -> second_low;
6111     ns     = time_ptr -> nanosecond;
6112 
6113     /* implement division on unsigned values */
6114     if ((sec_hi < 0) || (ns < 0))
6115     {
6116         _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
6117         ns = -ns;
6118         neg = 1;
6119     }
6120     else
6121     {
6122         neg = 0;
6123     }
6124 
6125     /* divide nanoseconds by two */
6126     ns >>= 1;
6127     if (sec_lo & 1)
6128     {
6129 
6130         /* add rest of seconds division */
6131         ns += 500000000L;
6132     }
6133 
6134     /* divide seconds by two */
6135     sec_lo >>= 1;
6136     if (sec_hi & 1)
6137     {
6138         sec_lo |= 0x80000000UL;
6139     }
6140     sec_hi >>= 1;
6141 
6142     /* restore sign */
6143     if (neg)
6144     {
6145         _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
6146         ns = -ns;
6147     }
6148 
6149     /* return result */
6150     time_ptr -> second_high = sec_hi;
6151     time_ptr -> second_low  = sec_lo;
6152     time_ptr -> nanosecond  = ns;
6153 }
6154