1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX PTP Client Component */
16 /** */
17 /** Precision Time Protocol (PTP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 /**************************************************************************/
23 /* */
24 /* APPLICATION INTERFACE DEFINITION RELEASE */
25 /* */
26 /* nxd_ptp_client.c PORTABLE C */
27 /* 6.1.3 */
28 /* AUTHOR */
29 /* */
30 /* Yuxin Zhou, Microsoft Corporation */
31 /* */
32 /* DESCRIPTION */
33 /* */
34 /* This file defines the NetX Precision Time Protocol (PTP) */
35 /* Client component, including all data types and external references. */
36 /* */
37 /* RELEASE HISTORY */
38 /* */
39 /* DATE NAME DESCRIPTION */
40 /* */
41 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
42 /* */
43 /**************************************************************************/
44
45
46 /* Force error checking to be disabled in this module */
47
48 #ifndef NX_DISABLE_ERROR_CHECKING
49 #define NX_DISABLE_ERROR_CHECKING
50 #endif
51
52 #define NX_PTP_SOURCE_CODE
53
54 #include "nxd_ptp_client.h"
55 #include "nx_udp.h"
56 #include "nx_ipv4.h"
57 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
58 #include "nx_ipv6.h"
59 #endif
60 #include "tx_timer.h"
61
62 /* #define NX_PTP_DEBUG */
63 /* #define NX_PTP_DEBUG_OFFSET */
64 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
65 #include <stdio.h>
66 #endif
67 #ifdef NX_PTP_DEBUG
68 #ifndef NX_PTP_DEBUG_PRINTF
69 #define NX_PTP_DEBUG_PRINTF(x) printf x
70 #endif
71 #else
72 #define NX_PTP_DEBUG_PRINTF(x)
73 #endif
74
75 /* Bring in externs for caller checking code. */
76
77 NX_CALLER_CHECKING_EXTERNS
78
79 /* number of nanoseconds per second */
80 #define NX_PTP_NANOSECONDS_PER_SEC 1000000000L
81
82 /* Define the PTP version */
83 #define NX_PTP_VERSION 2
84
85 /* Define the UDP ports */
86 #define NX_PTP_EVENT_UDP_PORT 319
87 #define NX_PTP_GENERAL_UDP_PORT 320
88
89 /* Define the TTL of PTP packets */
90 #define NX_PTP_TIME_TO_LIVE 1
91
92 /* Define the IPv4 multicast address "224.0.1.129" */
93 #define NX_PTP_IPV4_MULTICAST_ADDR IP_ADDRESS(224, 0, 1, 129)
94
95 /* Define the IPv6 multicast address "ff0e::181" */
96 #define NX_PTP_IPV6_MULTICAST_ADDR_SET(x) { \
97 (x) -> nxd_ip_version = NX_IP_VERSION_V6; \
98 (x) -> nxd_ip_address.v6[0] = 0xff0e0000UL; \
99 (x) -> nxd_ip_address.v6[1] = 0; \
100 (x) -> nxd_ip_address.v6[2] = 0; \
101 (x) -> nxd_ip_address.v6[3] = 0x181; }
102
103 /* Length of PTP message header */
104 #define NX_PTP_MSG_HDR_LEN 34
105
106 /* Length of PTP messages (without header) */
107 #define NX_PTP_MSG_ANNOUNCE_LEN 30
108 #define NX_PTP_MSG_SYNC_LEN 10
109 #define NX_PTP_MSG_FOLLOW_UP_LEN 10
110 #define NX_PTP_MSG_DELAY_RESP_LEN 20
111
112 /* Length of PTP timestamp */
113 #define NX_PTP_MSG_TIMESTAMP_LEN 10
114
115 /* Get version number */
116 #define NX_PTP_MSG_VERSION(p_) ((p_)[1] & 0xf)
117
118 /* Get domain number */
119 #define NX_PTP_MSG_DOMAIN(p_) ((p_)[4])
120
121 /* Type of messages */
122 #define NX_PTP_MSG_TYPE_SYNC 0
123 #define NX_PTP_MSG_TYPE_DELAY_REQ 1
124 #define NX_PTP_MSG_TYPE_FOLLOW_UP 8
125 #define NX_PTP_MSG_TYPE_DELAY_RESP 9
126 #define NX_PTP_MSG_TYPE_ANNOUNCE 11
127
128 /* Message flags */
129 #define NX_PTP_MSG_HDR_FLAG_LEAP61 (1 << 0)
130 #define NX_PTP_MSG_HDR_FLAG_LEAP59 (1 << 1)
131 #define NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE (1 << 2)
132 #define NX_PTP_MSG_HDR_FLAG_TWO_STEP (1 << 9)
133
134 /* Common Message Header */
135 typedef struct NX_PTP_MSG_HEADER_STRUCT
136 {
137 UCHAR transportSpecific;
138 UCHAR messageType;
139 UCHAR versionPTP;
140 UCHAR domainNumber;
141 USHORT messageLength;
142 USHORT flagField;
143 ULONG cFieldHigh;
144 ULONG cFieldLow;
145 UCHAR *sourcePortIdentity;
146 USHORT sequenceId;
147 UCHAR logMessageInterval;
148 } NX_PTP_MSG_HEADER;
149
150 /* Get UTC offset from announce message */
151 #define NX_PTP_MSG_UTC_OFFSET(p_) ((SHORT)((p_[10] << 8) | p_[11]))
152
153 /* Macros for reading PTP packet fields */
154 #define NX_PTP_RD16(p_, v_) { \
155 USHORT t_; \
156 t_ = *p_++; \
157 t_ = (USHORT)(t_ << 8); \
158 v_ = (USHORT)(t_ | *p_++); }
159
160 #define NX_PTP_RD32(p_, v_) { \
161 ULONG t_; \
162 t_ = *p_++; \
163 t_ <<= 8; \
164 t_ |= *p_++; \
165 t_ <<= 8; \
166 t_ |= *p_++; \
167 t_ <<= 8; \
168 v_ = t_ |= *p_++; }
169
170
171 /**************************************************************************/
172 /* */
173 /* FUNCTION RELEASE */
174 /* */
175 /* _nx_ptp_msg_parse_timestamp PORTABLE C */
176 /* 6.1.3 */
177 /* AUTHOR */
178 /* */
179 /* Yuxin Zhou, Microsoft Corporation */
180 /* */
181 /* DESCRIPTION */
182 /* */
183 /* This function parses timestamp field of a PTP message. */
184 /* */
185 /* INPUT */
186 /* */
187 /* ptr Pointer to PTP message */
188 /* time_ptr Pointer to PTP time for output*/
189 /* */
190 /* OUTPUT */
191 /* */
192 /* None */
193 /* */
194 /* CALLS */
195 /* */
196 /* None */
197 /* */
198 /* CALLED BY */
199 /* */
200 /* _nx_ptp_client_sync_received Process Sync message */
201 /* _nx_ptp_client_delay_resp_received Process delay response */
202 /* */
203 /* RELEASE HISTORY */
204 /* */
205 /* DATE NAME DESCRIPTION */
206 /* */
207 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
208 /* */
209 /**************************************************************************/
_nx_ptp_msg_parse_timestamp(UCHAR * ptr,NX_PTP_TIME * time_ptr)210 static VOID _nx_ptp_msg_parse_timestamp(UCHAR *ptr, NX_PTP_TIME *time_ptr)
211 {
212 ULONG nanoseconds = (ULONG)time_ptr -> nanosecond;
213
214 NX_PTP_RD16(ptr, time_ptr -> second_high);
215 NX_PTP_RD32(ptr, time_ptr -> second_low);
216 NX_PTP_RD32(ptr, nanoseconds);
217 time_ptr -> nanosecond = (LONG)nanoseconds;
218 }
219
220
221 /**************************************************************************/
222 /* */
223 /* FUNCTION RELEASE */
224 /* */
225 /* _nx_ptp_msg_parse_hdr PORTABLE C */
226 /* 6.1.3 */
227 /* AUTHOR */
228 /* */
229 /* Yuxin Zhou, Microsoft Corporation */
230 /* */
231 /* DESCRIPTION */
232 /* */
233 /* This function parses the header of a PTP packet. */
234 /* */
235 /* INPUT */
236 /* */
237 /* client_ptr Pointer to PTP client */
238 /* packet_ptr Pointer to PTP packet */
239 /* hdr Parsed PTP header for output */
240 /* */
241 /* OUTPUT */
242 /* */
243 /* status Completion status */
244 /* */
245 /* CALLS */
246 /* */
247 /* nxd_udp_packet_info_extract Extract UDP packet information*/
248 /* */
249 /* CALLED BY */
250 /* */
251 /* _nx_ptp_client_process_event_packet Process PTP event packet */
252 /* _nx_ptp_client_process_general_packet Process PTP general packet */
253 /* */
254 /* RELEASE HISTORY */
255 /* */
256 /* DATE NAME DESCRIPTION */
257 /* */
258 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
259 /* */
260 /**************************************************************************/
_nx_ptp_msg_parse_hdr(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_PTP_MSG_HEADER * hdr)261 static UINT _nx_ptp_msg_parse_hdr(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_MSG_HEADER *hdr)
262 {
263 UCHAR b;
264 UCHAR *ptr;
265 UINT len;
266 UINT status;
267 NXD_ADDRESS src_addr;
268 UINT interface_index;
269
270 #ifndef NX_DISABLE_PACKET_CHAIN
271 if (packet_ptr -> nx_packet_next)
272 {
273
274 /* Chained packet is not supported */
275 return(NX_NOT_SUPPORTED);
276 }
277 #endif /* NX_DISABLE_PACKET_CHAIN */
278
279 /* get pointer to PTP message */
280 ptr = packet_ptr -> nx_packet_prepend_ptr;
281
282 /* get length of PTP message */
283 len = packet_ptr -> nx_packet_length;
284
285 /* check packet validity: */
286 /* - length >= PTP header length */
287 /* - PTP version */
288 /* - domain number */
289 if ((len < NX_PTP_MSG_HDR_LEN) ||
290 (NX_PTP_MSG_VERSION(ptr) != NX_PTP_VERSION) ||
291 (NX_PTP_MSG_DOMAIN(ptr) != client_ptr -> nx_ptp_client_domain))
292 {
293
294 /* discard invalid packet */
295 return(NX_INVALID_PACKET);
296 }
297
298 /* get info about sender and check packet validity: */
299 /* - network interface */
300 /* - IP version */
301 status = nxd_udp_packet_info_extract(packet_ptr, &src_addr, NX_NULL, NX_NULL, &interface_index);
302 if ((status != NX_SUCCESS) ||
303 (interface_index != client_ptr -> nx_ptp_client_interface_index)
304 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
305 || ((src_addr.nxd_ip_version == NX_IP_VERSION_V4) &&
306 !client_ptr -> nx_ptp_client_ipv4_group_joined) ||
307 ((src_addr.nxd_ip_version == NX_IP_VERSION_V6) &&
308 !client_ptr -> nx_ptp_client_ipv6_group_joined)
309 #endif
310 )
311 {
312
313 /* discard invalid packet */
314 return(NX_INVALID_PACKET);
315 }
316
317 /* Save source address in listening state */
318 if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
319 {
320 client_ptr -> nx_ptp_client_master_addr = src_addr;
321 }
322
323 b = *ptr++;
324 hdr -> transportSpecific = b >> 4;
325 hdr -> messageType = b & 0xf;
326 b = *ptr++;
327 hdr -> versionPTP = b & 0xf;
328 NX_PTP_RD16(ptr, hdr -> messageLength);
329 hdr -> domainNumber = *ptr++;
330 ptr++; /* reserved */
331 NX_PTP_RD16(ptr, hdr -> flagField);
332 NX_PTP_RD32(ptr, hdr -> cFieldHigh);
333 NX_PTP_RD32(ptr, hdr -> cFieldLow);
334 ptr += 4; /* reserved */
335 hdr -> sourcePortIdentity = ptr;
336 ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
337 NX_PTP_RD16(ptr, hdr -> sequenceId);
338 ptr++; /* controlField - ignore */
339 hdr -> logMessageInterval = *ptr;
340
341 /* adjust message length */
342 if (len > hdr -> messageLength)
343 {
344 if (hdr -> messageLength < NX_PTP_MSG_HDR_LEN)
345 {
346
347 /* invalid length */
348 return(NX_INVALID_PACKET);
349 }
350 len = hdr -> messageLength;
351 }
352
353 /* Adjust packet. */
354 packet_ptr -> nx_packet_prepend_ptr += NX_PTP_MSG_HDR_LEN;
355 packet_ptr -> nx_packet_length = len - NX_PTP_MSG_HDR_LEN;
356
357 return(NX_SUCCESS);
358 }
359
360
361 /**************************************************************************/
362 /* */
363 /* FUNCTION RELEASE */
364 /* */
365 /* _nx_ptp_msg_parse_announce PORTABLE C */
366 /* 6.1.3 */
367 /* AUTHOR */
368 /* */
369 /* Yuxin Zhou, Microsoft Corporation */
370 /* */
371 /* DESCRIPTION */
372 /* */
373 /* This function parses PTP Announce message. */
374 /* */
375 /* INPUT */
376 /* */
377 /* ptr Pointer to PTP message */
378 /* master_ptr Parsed PTP master for output */
379 /* */
380 /* OUTPUT */
381 /* */
382 /* None */
383 /* */
384 /* CALLS */
385 /* */
386 /* None */
387 /* */
388 /* CALLED BY */
389 /* */
390 /* _nx_ptp_client_announce_received Process Announce message */
391 /* */
392 /* RELEASE HISTORY */
393 /* */
394 /* DATE NAME DESCRIPTION */
395 /* */
396 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
397 /* */
398 /**************************************************************************/
_nx_ptp_msg_parse_announce(UCHAR * ptr,NX_PTP_CLIENT_MASTER * master)399 static VOID _nx_ptp_msg_parse_announce(UCHAR *ptr, NX_PTP_CLIENT_MASTER *master)
400 {
401 ptr += NX_PTP_MSG_TIMESTAMP_LEN + 2 + 1; /* originTimestamp, utcOffset, reserved */
402 master -> nx_ptp_client_master_priority1 = *ptr++;
403 master -> nx_ptp_client_master_clock_class = *ptr++;
404 master -> nx_ptp_client_master_clock_accuracy = *ptr++;
405 NX_PTP_RD16(ptr, master -> nx_ptp_client_master_offset_scaled_log_variance);
406 master -> nx_ptp_client_master_priority2 = *ptr++;
407 master -> nx_ptp_client_master_grandmaster_identity = ptr;
408 ptr += NX_PTP_CLOCK_IDENTITY_SIZE;
409 NX_PTP_RD16(ptr, master -> nx_ptp_client_master_steps_removed);
410 master -> nx_ptp_client_master_time_source = *ptr;
411 }
412
413
414 /**************************************************************************/
415 /* */
416 /* FUNCTION RELEASE */
417 /* */
418 /* _nx_ptp_client_soft_clock_adjust PORTABLE C */
419 /* 6.1.3 */
420 /* AUTHOR */
421 /* */
422 /* Yuxin Zhou, Microsoft Corporation */
423 /* */
424 /* DESCRIPTION */
425 /* */
426 /* This function adjusts the value of the soft PTP clock. */
427 /* */
428 /* INPUT */
429 /* */
430 /* ptp_instance Pointer to PTP client */
431 /* offset_ns Signed number of nanoseconds */
432 /* to add to the PTP clock */
433 /* */
434 /* OUTPUT */
435 /* */
436 /* None */
437 /* */
438 /* CALLS */
439 /* */
440 /* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
441 /* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
442 /* */
443 /* CALLED BY */
444 /* */
445 /* _nx_ptp_client_soft_clock_callback Soft PTP clock */
446 /* */
447 /* RELEASE HISTORY */
448 /* */
449 /* DATE NAME DESCRIPTION */
450 /* */
451 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
452 /* */
453 /**************************************************************************/
_nx_ptp_client_soft_clock_adjust(VOID * ptp_instance,LONG offset_ns)454 static VOID _nx_ptp_client_soft_clock_adjust(VOID *ptp_instance, LONG offset_ns)
455 {
456 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
457 TX_INTERRUPT_SAVE_AREA
458
459 /* enforce min/max values of offset */
460 if (offset_ns > NX_PTP_NANOSECONDS_PER_SEC)
461 {
462 offset_ns = NX_PTP_NANOSECONDS_PER_SEC;
463 }
464 else if (offset_ns < -NX_PTP_NANOSECONDS_PER_SEC)
465 {
466 offset_ns = -NX_PTP_NANOSECONDS_PER_SEC;
467 }
468
469 /* add the number of nanosecond to the current time */
470 TX_DISABLE
471 client_ptr -> nx_ptp_client_soft_clock.nanosecond += offset_ns;
472 if (client_ptr -> nx_ptp_client_soft_clock.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
473 {
474 client_ptr -> nx_ptp_client_soft_clock.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
475 _nx_ptp_client_utility_inc64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
476 &client_ptr -> nx_ptp_client_soft_clock.second_low);
477 }
478 else if (client_ptr -> nx_ptp_client_soft_clock.nanosecond < 0)
479 {
480 client_ptr -> nx_ptp_client_soft_clock.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
481 _nx_ptp_client_utility_dec64(&client_ptr -> nx_ptp_client_soft_clock.second_high,
482 &client_ptr -> nx_ptp_client_soft_clock.second_low);
483 }
484 TX_RESTORE
485 }
486
487
488 /**************************************************************************/
489 /* */
490 /* FUNCTION RELEASE */
491 /* */
492 /* _nx_ptp_client_timer_handler PORTABLE C */
493 /* 6.1.3 */
494 /* AUTHOR */
495 /* */
496 /* Yuxin Zhou, Microsoft Corporation */
497 /* */
498 /* DESCRIPTION */
499 /* */
500 /* This function implements the PTP client timer handler. */
501 /* */
502 /* INPUT */
503 /* */
504 /* ptp_instance Pointer to PTP client */
505 /* */
506 /* OUTPUT */
507 /* */
508 /* None */
509 /* */
510 /* CALLS */
511 /* */
512 /* tx_event_flags_set Set PTP timer event */
513 /* */
514 /* CALLED BY */
515 /* */
516 /* ThreadX Timer */
517 /* */
518 /* RELEASE HISTORY */
519 /* */
520 /* DATE NAME DESCRIPTION */
521 /* */
522 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
523 /* */
524 /**************************************************************************/
_nx_ptp_client_timer_handler(ULONG ptp_instance)525 static VOID _nx_ptp_client_timer_handler(ULONG ptp_instance)
526 {
527 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
528
529 /* Update soft timer. */
530 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE,
531 &client_ptr -> nx_ptp_client_soft_clock, NX_NULL,
532 client_ptr -> nx_ptp_client_clock_callback_data);
533
534 /* set timer event */
535 tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_TIMER_EVENT, TX_OR);
536 }
537
538
539 /**************************************************************************/
540 /* */
541 /* FUNCTION RELEASE */
542 /* */
543 /* _nx_ptp_client_socket_receive_notify PORTABLE C */
544 /* 6.1.3 */
545 /* AUTHOR */
546 /* */
547 /* Yuxin Zhou, Microsoft Corporation */
548 /* */
549 /* DESCRIPTION */
550 /* */
551 /* This function is invoked when UDP packet is received. */
552 /* */
553 /* INPUT */
554 /* */
555 /* socket_ptr Pointer to general socket */
556 /* */
557 /* OUTPUT */
558 /* */
559 /* None */
560 /* */
561 /* CALLS */
562 /* */
563 /* tx_event_flags_set Set UDP receive event */
564 /* */
565 /* CALLED BY */
566 /* */
567 /* NetX UDP */
568 /* */
569 /* RELEASE HISTORY */
570 /* */
571 /* DATE NAME DESCRIPTION */
572 /* */
573 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
574 /* */
575 /**************************************************************************/
_nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET * socket_ptr)576 static VOID _nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET *socket_ptr)
577 {
578 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)(socket_ptr -> nx_udp_socket_reserved_ptr);
579
580 /* set timer event */
581 tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR);
582 }
583
584
585 /**************************************************************************/
586 /* */
587 /* FUNCTION RELEASE */
588 /* */
589 /* _nx_ptp_client_clock_adjust PORTABLE C */
590 /* 6.1.3 */
591 /* AUTHOR */
592 /* */
593 /* Yuxin Zhou, Microsoft Corporation */
594 /* */
595 /* DESCRIPTION */
596 /* */
597 /* Adjust the PTP clock with the given offset */
598 /* If the offset is greater than one second, the clock is updated, */
599 /* otherwise it is adjusted with the number of nanoseconds. */
600 /* */
601 /* INPUT */
602 /* */
603 /* client_ptr Pointer to PTP client */
604 /* offset_ptr Pointer to time offset */
605 /* */
606 /* OUTPUT */
607 /* */
608 /* None */
609 /* */
610 /* CALLS */
611 /* */
612 /* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
613 /* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
614 /* _nx_ptp_client_utility_add64 Add two 64-bit number */
615 /* */
616 /* CALLED BY */
617 /* */
618 /* _nx_ptp_client_delay_resp_received Process delay response */
619 /* */
620 /* RELEASE HISTORY */
621 /* */
622 /* DATE NAME DESCRIPTION */
623 /* */
624 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
625 /* */
626 /**************************************************************************/
_nx_ptp_client_clock_adjust(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * offset_ptr)627 static VOID _nx_ptp_client_clock_adjust(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *offset_ptr)
628 {
629 NX_PTP_TIME current;
630
631 if ((offset_ptr -> second_high == 0) && (offset_ptr -> second_low == 0))
632 {
633
634 /* offset less than 1s, adjust clock */
635 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_ADJUST, offset_ptr, NX_NULL,
636 client_ptr -> nx_ptp_client_clock_callback_data);
637 NX_PTP_DEBUG_PRINTF(("PTP: adjust clock %d ns\r\n", (INT)offset_ptr -> nanosecond));
638 }
639 else
640 {
641
642 /* offset greater than 1s, set new clock value */
643 /* get current clock value */
644 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, ¤t, NX_NULL,
645 client_ptr -> nx_ptp_client_clock_callback_data);
646
647 /* add nanoseconds offset */
648 current.nanosecond += offset_ptr -> nanosecond;
649
650 /* ensure nanosecond field is in range 0-999999999 */
651 if (current.nanosecond < 0)
652 {
653 current.nanosecond += NX_PTP_NANOSECONDS_PER_SEC;
654 _nx_ptp_client_utility_dec64(¤t.second_high, ¤t.second_low);
655 }
656 else if (current.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
657 {
658 current.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
659 _nx_ptp_client_utility_inc64(¤t.second_high, ¤t.second_low);
660 }
661
662 /* add seconds offset */
663 _nx_ptp_client_utility_add64(¤t.second_high, ¤t.second_low,
664 offset_ptr -> second_high, offset_ptr -> second_low);
665
666 /* set new clock value */
667 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, ¤t, NX_NULL,
668 client_ptr -> nx_ptp_client_clock_callback_data);
669
670 NX_PTP_DEBUG_PRINTF(("PTP: set clock %u.%d\r\n",
671 (UINT)current.second_low,
672 (INT)current.nanosecond));
673 }
674 }
675
676
677 /**************************************************************************/
678 /* */
679 /* FUNCTION RELEASE */
680 /* */
681 /* _nx_ptp_client_send_delay_req PORTABLE C */
682 /* 6.1.3 */
683 /* AUTHOR */
684 /* */
685 /* Yuxin Zhou, Microsoft Corporation */
686 /* */
687 /* DESCRIPTION */
688 /* */
689 /* This function sends a PTP Delay Request message. */
690 /* */
691 /* INPUT */
692 /* */
693 /* client_ptr Pointer to PTP client */
694 /* */
695 /* OUTPUT */
696 /* */
697 /* None */
698 /* */
699 /* CALLS */
700 /* */
701 /* nx_packet_allocate Allocate a packet */
702 /* nxd_udp_socket_source_send Send a UDP packet */
703 /* nx_packet_release Release a packet */
704 /* */
705 /* CALLED BY */
706 /* */
707 /* _nx_ptp_client_sync_received Process Sync message */
708 /* */
709 /* RELEASE HISTORY */
710 /* */
711 /* DATE NAME DESCRIPTION */
712 /* */
713 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
714 /* */
715 /**************************************************************************/
_nx_ptp_client_send_delay_req(NX_PTP_CLIENT * client_ptr)716 static VOID _nx_ptp_client_send_delay_req(NX_PTP_CLIENT *client_ptr)
717 {
718 NX_PACKET *packet_ptr;
719 UINT status = NX_NOT_SUCCESSFUL;
720 UCHAR *ptr;
721 NXD_ADDRESS addr;
722 UINT addr_index = 0;
723 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
724 NXD_IPV6_ADDRESS *ipv6_addr;
725 NX_IP *ip_ptr;
726 NX_INTERFACE *if_ptr;
727 #endif
728
729 NX_PTP_DEBUG_PRINTF(("PTP: send DELAY_REQ\r\n"));
730
731 /* allocate a packet from the pool */
732 status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_NO_WAIT);
733 if (status != NX_SUCCESS)
734 {
735 /* Failed to allocate the packet */
736 return;
737 }
738
739 /* start of message */
740 ptr = packet_ptr -> nx_packet_prepend_ptr;
741
742 #define PTP_MSG_DELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN)
743 #define PTP_MSG_DELAY_REQ_ZERO1_LEN (1 + 2 + 8 + 4)
744
745 /* write header */
746 *ptr++ = NX_PTP_MSG_TYPE_DELAY_REQ;
747 *ptr++ = NX_PTP_VERSION;
748 *ptr++ = PTP_MSG_DELAY_REQ_TOTAL_LEN >> 8;
749 *ptr++ = (UCHAR)PTP_MSG_DELAY_REQ_TOTAL_LEN;
750 *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | client_ptr -> nx_ptp_client_domain;
751 memset(ptr, 0, PTP_MSG_DELAY_REQ_ZERO1_LEN); /* reserved/flags/correction/reserved */
752 ptr += PTP_MSG_DELAY_REQ_ZERO1_LEN;
753 memcpy(ptr, client_ptr -> nx_ptp_client_port_identity,
754 NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
755 ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
756 client_ptr -> nx_ptp_client_delay_req_id++;
757 *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_delay_req_id >> 8);
758 *ptr++ = (UCHAR)client_ptr -> nx_ptp_client_delay_req_id;
759 *ptr++ = 0; /* control */
760 *ptr++ = 0; /* XXX */
761
762 /* write timestamp (0) */
763 memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN);
764 ptr += NX_PTP_MSG_TIMESTAMP_LEN;
765
766 /* set final length of message */
767 packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr);
768 packet_ptr -> nx_packet_append_ptr = ptr;
769
770 /* set source and destination addresses */
771 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
772 if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6)
773 {
774 NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr);
775
776 /* Use first IPv6 address as source address. */
777 ip_ptr = client_ptr -> nx_ptp_client_ip_ptr;
778 if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index];
779 ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head;
780 if (ipv6_addr == NX_NULL)
781 {
782
783 /* No available IPv6 address. */
784 /* Release packet. */
785 nx_packet_release(packet_ptr);
786
787 /* Reset state. */
788 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
789 client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
790
791 return;
792 }
793 addr_index = ipv6_addr -> nxd_ipv6_address_index;
794 }
795 else
796 #endif
797 {
798 #ifndef NX_DISABLE_IPV4
799 addr.nxd_ip_version = NX_IP_VERSION_V4;
800 addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR;
801 addr_index = client_ptr -> nx_ptp_client_interface_index;
802 #endif
803 }
804
805 /* Prepare timestamp for current packet */
806 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_REQ_TS;
807 client_ptr -> nx_ptp_client_delay_req_packet_ptr = packet_ptr;
808 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE,
809 &client_ptr -> nx_ptp_client_delay_ts, packet_ptr,
810 client_ptr -> nx_ptp_client_clock_callback_data);
811
812 /* Send delay request */
813 status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
814 packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index);
815 if (status)
816 {
817
818 /* release packet in case of error */
819 nx_packet_release(packet_ptr);
820
821 /* reset state */
822 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
823 client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL;
824
825 return;
826 }
827
828 /* rearm delay req timer */
829 client_ptr -> nx_ptp_client_delay_req_timer = NX_PTP_CLIENT_DELAY_REQ_INTERVAL;
830 client_ptr -> nx_ptp_client_delay_req_flag = 0;
831 }
832
833
834 /**************************************************************************/
835 /* */
836 /* FUNCTION RELEASE */
837 /* */
838 /* _nx_ptp_client_sync_received PORTABLE C */
839 /* 6.1.3 */
840 /* AUTHOR */
841 /* */
842 /* Yuxin Zhou, Microsoft Corporation */
843 /* */
844 /* DESCRIPTION */
845 /* */
846 /* This function processes a received PTP Sync message. */
847 /* */
848 /* INPUT */
849 /* */
850 /* client_ptr Pointer to PTP client */
851 /* ts_ptr Pointer to the timestamp */
852 /* delivered by the Sync message*/
853 /* */
854 /* OUTPUT */
855 /* */
856 /* None */
857 /* */
858 /* CALLS */
859 /* */
860 /* _nx_ptp_msg_parse_timestamp Parse timestamp field */
861 /* _nx_ptp_client_send_delay_req Send delay request */
862 /* */
863 /* CALLED BY */
864 /* */
865 /* _nx_ptp_client_process_event_packet Process PTP event packet */
866 /* _nx_ptp_client_process_general_packet Process PTP general packet */
867 /* */
868 /* RELEASE HISTORY */
869 /* */
870 /* DATE NAME DESCRIPTION */
871 /* */
872 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
873 /* */
874 /**************************************************************************/
_nx_ptp_client_sync_received(NX_PTP_CLIENT * client_ptr,VOID * ts_ptr)875 static VOID _nx_ptp_client_sync_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
876 {
877 NX_PTP_DEBUG_PRINTF(("PTP: rcv SYNC\r\n"));
878
879 /* store Sync master timestamp */
880 _nx_ptp_msg_parse_timestamp(ts_ptr, &client_ptr -> nx_ptp_client_sync);
881
882 /* delay and offset determination */
883 if (client_ptr -> nx_ptp_client_delay_req_flag)
884 {
885
886 /* send delay request message */
887 /* (delay_req_flag is cleared by this function) */
888 _nx_ptp_client_send_delay_req(client_ptr);
889 }
890
891 /* update Sync state */
892 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC;
893 }
894
895
896 /**************************************************************************/
897 /* */
898 /* FUNCTION RELEASE */
899 /* */
900 /* _nx_ptp_client_delay_resp_received PORTABLE C */
901 /* 6.1.5 */
902 /* AUTHOR */
903 /* */
904 /* Yuxin Zhou, Microsoft Corporation */
905 /* */
906 /* DESCRIPTION */
907 /* */
908 /* This function processes a received PTP Delay Response message. */
909 /* */
910 /* INPUT */
911 /* */
912 /* client_ptr Pointer to PTP client */
913 /* ts_ptr Pointer to the timestamp */
914 /* delivered by the Delay Resp */
915 /* message */
916 /* */
917 /* OUTPUT */
918 /* */
919 /* None */
920 /* */
921 /* CALLS */
922 /* */
923 /* _nx_ptp_client_clock_adjust Adjust PTP clock */
924 /* _nx_ptp_msg_parse_timestamp Parse timestamp field */
925 /* _nx_ptp_client_utility_time_diff Diff two PTP times */
926 /* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */
927 /* */
928 /* CALLED BY */
929 /* */
930 /* _nx_ptp_client_process_general_packet Process PTP general packet */
931 /* */
932 /* RELEASE HISTORY */
933 /* */
934 /* DATE NAME DESCRIPTION */
935 /* */
936 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
937 /* 03-02-2021 Yuxin Zhou Modified comment(s), and */
938 /* fixed compiler warnings, */
939 /* resulting in version 6.1.5 */
940 /* */
941 /**************************************************************************/
_nx_ptp_client_delay_resp_received(NX_PTP_CLIENT * client_ptr,VOID * ts_ptr)942 static VOID _nx_ptp_client_delay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr)
943 {
944 NX_PTP_TIME t4, a, b;
945 NX_PTP_CLIENT_SYNC sync;
946
947 NX_PTP_DEBUG_PRINTF(("PTP: rcv DELAY_RESP\r\n"));
948
949 /*
950 * The following timestamps are used for delay/offset determination:
951 *
952 * t1 = nx_ptp_client_sync
953 * t2 = nx_ptp_client_sync_ts
954 * t3 = nx_ptp_client_delay_ts
955 * t4 = timestamp in Delay_Resp message (ts_ptr)
956 *
957 * A = t2 - t1
958 * B = t4 - t3
959 *
960 * delay = (A + B) / 2
961 * offset = (B - A) / 2
962 */
963
964 /* check for valid timestamp t1 */
965 if ((client_ptr -> nx_ptp_client_sync.second_low == 0) &&
966 (client_ptr -> nx_ptp_client_sync.second_high == 0))
967 {
968 return;
969 }
970
971 /* get master clock timestamp */
972 _nx_ptp_msg_parse_timestamp(ts_ptr, &t4);
973
974 /* compute A = t2 - t1 */
975 _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts, &client_ptr -> nx_ptp_client_sync, &a);
976
977 /* compute B = t4 - t3 */
978 _nx_ptp_client_utility_time_diff(&t4, &client_ptr -> nx_ptp_client_delay_ts, &b);
979
980 /* compute offset = (B - A) / 2 */
981 _nx_ptp_client_utility_time_diff(&b, &a, &a);
982 _nx_ptp_client_utility_time_div_by_2(&a);
983
984 #if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET)
985 if ((a.second_low == 0) && (a.second_high == 0))
986 {
987 if ((a.nanosecond > -1000) && (a.nanosecond < 1000))
988 {
989 printf("PTP: offset = %ld ns\n", a.nanosecond);
990 }
991 else if ((a.nanosecond > -1000000) && (a.nanosecond < 1000000))
992 {
993 printf("PTP: offset = %ld us\n", a.nanosecond / 1000);
994 }
995 else
996 {
997 printf("PTP: offset = %ld ms\n", a.nanosecond / 1000000);
998 }
999 }
1000 else
1001 {
1002 printf("PTP: offset > 1s\n");
1003 }
1004 #endif
1005
1006 /* add the time offset the client clock */
1007 _nx_ptp_client_clock_adjust(client_ptr, &a);
1008
1009 /* set calibrated flag */
1010 if (!(client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED))
1011 {
1012
1013 client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED;
1014
1015 /* application callback */
1016 if (client_ptr -> nx_ptp_client_event_callback)
1017 {
1018 sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags;
1019 sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset;
1020 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
1021 client_ptr -> nx_ptp_client_event_callback_data);
1022 }
1023 }
1024
1025 /* update delay req state */
1026 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1027 }
1028
1029
1030 /**************************************************************************/
1031 /* */
1032 /* FUNCTION RELEASE */
1033 /* */
1034 /* _nx_ptp_client_announce_received PORTABLE C */
1035 /* 6.1.3 */
1036 /* AUTHOR */
1037 /* */
1038 /* Yuxin Zhou, Microsoft Corporation */
1039 /* */
1040 /* DESCRIPTION */
1041 /* */
1042 /* This function processes a received PTP Announce message. */
1043 /* */
1044 /* INPUT */
1045 /* */
1046 /* client_ptr Pointer to PTP client */
1047 /* hdr Pointer to PTP header */
1048 /* ptr Pointer to PTP message */
1049 /* */
1050 /* OUTPUT */
1051 /* */
1052 /* None */
1053 /* */
1054 /* CALLS */
1055 /* */
1056 /* _nx_ptp_msg_parse_announce Parse Announce message */
1057 /* memcpy Copy memory */
1058 /* */
1059 /* CALLED BY */
1060 /* */
1061 /* _nx_ptp_client_process_general_packet Process PTP general packet */
1062 /* */
1063 /* RELEASE HISTORY */
1064 /* */
1065 /* DATE NAME DESCRIPTION */
1066 /* */
1067 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1068 /* */
1069 /**************************************************************************/
_nx_ptp_client_announce_received(NX_PTP_CLIENT * client_ptr,NX_PTP_MSG_HEADER * hdr,UCHAR * ptr)1070 static VOID _nx_ptp_client_announce_received(NX_PTP_CLIENT *client_ptr,
1071 NX_PTP_MSG_HEADER *hdr,
1072 UCHAR *ptr)
1073 {
1074 NX_PTP_CLIENT_SYNC sync;
1075 NX_PTP_CLIENT_MASTER master;
1076
1077 /* parse Sync information */
1078 sync.nx_ptp_client_sync_flags = 0;
1079 if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE)
1080 {
1081 sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_UTC_REASONABLE;
1082 }
1083 if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP59)
1084 {
1085 sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP59;
1086 }
1087 if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP61)
1088 {
1089 sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP61;
1090 }
1091 sync.nx_ptp_client_sync_utc_offset = NX_PTP_MSG_UTC_OFFSET(ptr);
1092
1093 /* check for new master */
1094 if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING)
1095 {
1096
1097 /* first announce message, save master clock parameters */
1098 client_ptr -> nx_ptp_client_sync_flags = sync.nx_ptp_client_sync_flags;
1099 client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
1100 memcpy(client_ptr -> nx_ptp_client_master_port_identity, hdr -> sourcePortIdentity,
1101 NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
1102
1103 /* wait for Sync message */
1104 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC;
1105 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE;
1106 client_ptr -> nx_ptp_client_delay_req_timer = -1;
1107 client_ptr -> nx_ptp_client_delay_req_flag = 1;
1108
1109
1110 /* call application callback */
1111 if (client_ptr -> nx_ptp_client_event_callback)
1112 {
1113
1114 /* parse annouce message */
1115 _nx_ptp_msg_parse_announce(ptr, &master);
1116 master.nx_ptp_client_master_address = &(client_ptr -> nx_ptp_client_master_addr);
1117 master.nx_ptp_client_master_port_identity = hdr -> sourcePortIdentity;
1118 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER, &master,
1119 client_ptr -> nx_ptp_client_event_callback_data);
1120 }
1121 }
1122 else
1123 {
1124
1125 /* check for UTC offset update or flags changes */
1126 if (((client_ptr -> nx_ptp_client_sync_flags & ~NX_PTP_CLIENT_SYNC_CALIBRATED) !=
1127 sync.nx_ptp_client_sync_flags) ||
1128 (client_ptr -> nx_ptp_client_utc_offset != sync.nx_ptp_client_sync_utc_offset))
1129 {
1130 client_ptr -> nx_ptp_client_sync_flags =
1131 (USHORT)((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) |
1132 sync.nx_ptp_client_sync_flags);
1133 client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset;
1134
1135 /* call application callback */
1136 if ((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) &&
1137 (client_ptr -> nx_ptp_client_event_callback))
1138 {
1139 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync,
1140 client_ptr -> nx_ptp_client_event_callback_data);
1141 }
1142 }
1143 }
1144
1145 /* reset annouce timer */
1146 client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION;
1147 }
1148
1149
1150 /**************************************************************************/
1151 /* */
1152 /* FUNCTION RELEASE */
1153 /* */
1154 /* _nx_ptp_client_process_event_packet PORTABLE C */
1155 /* 6.1.3 */
1156 /* AUTHOR */
1157 /* */
1158 /* Yuxin Zhou, Microsoft Corporation */
1159 /* */
1160 /* DESCRIPTION */
1161 /* */
1162 /* This function processes PTP packet received through event socket. */
1163 /* */
1164 /* INPUT */
1165 /* */
1166 /* client_ptr Pointer to PTP client */
1167 /* packet_ptr Pointer to PTP packet */
1168 /* */
1169 /* OUTPUT */
1170 /* */
1171 /* None */
1172 /* */
1173 /* CALLS */
1174 /* */
1175 /* _nx_ptp_client_sync_received Process Sync message */
1176 /* _nx_ptp_msg_parse_hdr Parse PTP header */
1177 /* memcmp Compare memory */
1178 /* */
1179 /* CALLED BY */
1180 /* */
1181 /* _nx_ptp_client_thread_entry PTP thread entry */
1182 /* */
1183 /* RELEASE HISTORY */
1184 /* */
1185 /* DATE NAME DESCRIPTION */
1186 /* */
1187 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1188 /* */
1189 /**************************************************************************/
_nx_ptp_client_process_event_packet(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr)1190 static VOID _nx_ptp_client_process_event_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
1191 {
1192 NX_PTP_MSG_HEADER hdr;
1193
1194 /* parse PTP message header */
1195 if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr))
1196 {
1197 return;
1198 }
1199
1200 /* check origin of message */
1201 if (memcmp(&client_ptr -> nx_ptp_client_master_port_identity,
1202 hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)
1203 {
1204
1205 /* not from our master clock */
1206 return;
1207 }
1208
1209 if (hdr.messageType != NX_PTP_MSG_TYPE_SYNC)
1210 {
1211 return;
1212 }
1213
1214 if (((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_SYNC) &&
1215 (client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP)) ||
1216 (packet_ptr -> nx_packet_length < NX_PTP_MSG_SYNC_LEN))
1217 {
1218
1219 /* not waiting for Sync or invalid message */
1220 return;
1221 }
1222
1223 /* retrieve timestamp of event message */
1224 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT,
1225 &client_ptr -> nx_ptp_client_sync_ts, packet_ptr,
1226 client_ptr -> nx_ptp_client_clock_callback_data);
1227
1228 /* two-step message? */
1229 if (hdr.flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP)
1230 {
1231
1232 /* wait for follow up message */
1233 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP;
1234 client_ptr -> nx_ptp_client_sync_id = hdr.sequenceId;
1235 }
1236 else
1237 {
1238
1239 /* process Sync event */
1240 _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
1241 }
1242 }
1243
1244
1245 /**************************************************************************/
1246 /* */
1247 /* FUNCTION RELEASE */
1248 /* */
1249 /* _nx_ptp_client_process_general_packet PORTABLE C */
1250 /* 6.1.3 */
1251 /* AUTHOR */
1252 /* */
1253 /* Yuxin Zhou, Microsoft Corporation */
1254 /* */
1255 /* DESCRIPTION */
1256 /* */
1257 /* This function processes PTP packet received through general socket. */
1258 /* */
1259 /* INPUT */
1260 /* */
1261 /* client_ptr Pointer to PTP client */
1262 /* packet_ptr Pointer to PTP packet */
1263 /* */
1264 /* OUTPUT */
1265 /* */
1266 /* None */
1267 /* */
1268 /* CALLS */
1269 /* */
1270 /* _nx_ptp_client_sync_received Process Sync message */
1271 /* _nx_ptp_msg_parse_hdr Parse PTP header */
1272 /* _nx_ptp_client_delay_resp_received Process delay response */
1273 /* _nx_ptp_client_announce_received Process Announce message */
1274 /* memcmp Compare memory */
1275 /* */
1276 /* CALLED BY */
1277 /* */
1278 /* _nx_ptp_client_thread_entry PTP thread entry */
1279 /* */
1280 /* RELEASE HISTORY */
1281 /* */
1282 /* DATE NAME DESCRIPTION */
1283 /* */
1284 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1285 /* */
1286 /**************************************************************************/
_nx_ptp_client_process_general_packet(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr)1287 static VOID _nx_ptp_client_process_general_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr)
1288 {
1289 NX_PTP_MSG_HEADER hdr;
1290
1291 /* parse PTP message header */
1292 if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr))
1293 {
1294 return;
1295 }
1296
1297 /* check origin of message */
1298 if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_LISTENING) &&
1299 (memcmp(&client_ptr -> nx_ptp_client_master_port_identity,
1300 hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
1301 {
1302
1303 /* not from our master clock */
1304 return;
1305 }
1306
1307 /* process ANNOUNCE message */
1308 if (hdr.messageType == NX_PTP_MSG_TYPE_ANNOUNCE)
1309 {
1310 if (packet_ptr -> nx_packet_length < NX_PTP_MSG_ANNOUNCE_LEN)
1311 {
1312
1313 /* invalid message */
1314 return;
1315 }
1316
1317 /* process announce message */
1318 _nx_ptp_client_announce_received(client_ptr, &hdr, packet_ptr -> nx_packet_prepend_ptr);
1319 }
1320 else if (hdr.messageType == NX_PTP_MSG_TYPE_FOLLOW_UP)
1321 {
1322 if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP) ||
1323 (client_ptr -> nx_ptp_client_sync_id != hdr.sequenceId) ||
1324 (packet_ptr -> nx_packet_length < NX_PTP_MSG_FOLLOW_UP_LEN))
1325 {
1326
1327 /* not a follow up for a previous Sync or invalid message */
1328 return;
1329 }
1330
1331 /* process Sync message */
1332 _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
1333 }
1334 else if (hdr.messageType == NX_PTP_MSG_TYPE_DELAY_RESP)
1335 {
1336 if ((client_ptr -> nx_ptp_client_delay_state != NX_PTP_CLIENT_DELAY_WAIT_RESP) ||
1337 (client_ptr -> nx_ptp_client_delay_req_id != hdr.sequenceId) ||
1338 (packet_ptr -> nx_packet_length < NX_PTP_MSG_DELAY_RESP_LEN) ||
1339 (memcmp(client_ptr -> nx_ptp_client_port_identity,
1340 packet_ptr -> nx_packet_prepend_ptr + NX_PTP_MSG_TIMESTAMP_LEN,
1341 NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0))
1342 {
1343
1344 /* not a delay_resp for a previous delay_req or invalid message */
1345 return;
1346 }
1347
1348 /* process delay response message */
1349 _nx_ptp_client_delay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr);
1350 }
1351 }
1352
1353
1354 /**************************************************************************/
1355 /* */
1356 /* FUNCTION RELEASE */
1357 /* */
1358 /* _nx_ptp_client_thread_entry PORTABLE C */
1359 /* 6.1.3 */
1360 /* AUTHOR */
1361 /* */
1362 /* Yuxin Zhou, Microsoft Corporation */
1363 /* */
1364 /* DESCRIPTION */
1365 /* */
1366 /* This function implements the PTP client processing thread. */
1367 /* */
1368 /* INPUT */
1369 /* */
1370 /* ptp_instance Pointer to PTP client */
1371 /* */
1372 /* OUTPUT */
1373 /* */
1374 /* None */
1375 /* */
1376 /* CALLS */
1377 /* */
1378 /* _nx_ptp_client_process_general_packet Process PTP general packet */
1379 /* _nx_ptp_client_process_event_packet Process PTP event packet */
1380 /* tx_event_flags_get Get PTP events */
1381 /* nx_udp_socket_receive Receive a UDP packet */
1382 /* nx_packet_release Release a packet */
1383 /* */
1384 /* CALLED BY */
1385 /* */
1386 /* ThreadX */
1387 /* */
1388 /* RELEASE HISTORY */
1389 /* */
1390 /* DATE NAME DESCRIPTION */
1391 /* */
1392 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1393 /* */
1394 /**************************************************************************/
_nx_ptp_client_thread_entry(ULONG ptp_instance)1395 static VOID _nx_ptp_client_thread_entry(ULONG ptp_instance)
1396 {
1397 TX_INTERRUPT_SAVE_AREA
1398 NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance;
1399 ULONG ptp_events;
1400 UINT status;
1401 NX_PACKET *packet_ptr = NX_NULL;
1402 UCHAR packet_received;
1403
1404 /* start in listening state */
1405 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
1406 client_ptr -> nx_ptp_client_delay_req_timer = -1;
1407 client_ptr -> nx_ptp_client_announce_timeout = -1;
1408
1409 /* main loop */
1410 for (;;)
1411 {
1412
1413 /* wait for message */
1414 status = tx_event_flags_get(&(client_ptr -> nx_ptp_client_events),
1415 NX_PTP_CLIENT_ALL_EVENTS, TX_OR_CLEAR,
1416 &ptp_events, TX_WAIT_FOREVER);
1417 if (status != TX_SUCCESS)
1418 {
1419
1420 /* error while reading queue, abort thread */
1421 break;
1422 }
1423
1424 if (ptp_events & NX_PTP_CLIENT_STOP_EVENT)
1425 {
1426
1427 /* terminate thread */
1428 break;
1429 }
1430
1431 /*
1432 * PTP Message Received
1433 */
1434 if (ptp_events & NX_PTP_CLIENT_RX_EVENT)
1435 {
1436
1437 /* Loop to receive all packets. */
1438 for (;;)
1439 {
1440 packet_received = NX_FALSE;
1441 if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_general_socket),
1442 &packet_ptr, NX_NO_WAIT) == NX_SUCCESS)
1443 {
1444 _nx_ptp_client_process_general_packet(client_ptr, packet_ptr);
1445
1446 /* Release packet. */
1447 nx_packet_release(packet_ptr);
1448 packet_received = NX_TRUE;
1449 }
1450
1451 if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_event_socket),
1452 &packet_ptr, NX_NO_WAIT) == NX_SUCCESS)
1453 {
1454 _nx_ptp_client_process_event_packet(client_ptr, packet_ptr);
1455
1456 /* Release packet. */
1457 nx_packet_release(packet_ptr);
1458 packet_received = NX_TRUE;
1459 }
1460
1461 if (packet_received == NX_FALSE)
1462 {
1463
1464 /* No more packets available. */
1465 break;
1466 }
1467 }
1468 }
1469
1470 /*
1471 * Timer Event
1472 */
1473 if (ptp_events & NX_PTP_CLIENT_TIMER_EVENT)
1474 {
1475
1476 /* announce messages timeout */
1477 if ((client_ptr -> nx_ptp_client_announce_timeout > 0) &&
1478 (--client_ptr -> nx_ptp_client_announce_timeout == 0))
1479 {
1480
1481 /* no Annouce message received from master clock, back to listening state */
1482 client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING;
1483 client_ptr -> nx_ptp_client_delay_req_timer = -1;
1484 client_ptr -> nx_ptp_client_announce_timeout = -1;
1485
1486 /* call handler */
1487 if (client_ptr -> nx_ptp_client_event_callback)
1488 {
1489 client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_TIMEOUT, NX_NULL,
1490 client_ptr -> nx_ptp_client_event_callback_data);
1491 }
1492 }
1493
1494 /* delay req interval timer */
1495 if ((client_ptr -> nx_ptp_client_delay_req_timer > 0) &&
1496 (--client_ptr -> nx_ptp_client_delay_req_timer == 0))
1497 {
1498
1499 /* set flag */
1500 client_ptr -> nx_ptp_client_delay_req_flag = 1;
1501 }
1502 }
1503 }
1504
1505 /* set stopped state */
1506 TX_DISABLE
1507 client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPED;
1508 TX_RESTORE
1509 }
1510
1511
1512 /**************************************************************************/
1513 /* */
1514 /* FUNCTION RELEASE */
1515 /* */
1516 /* _nxe_ptp_client_create PORTABLE C */
1517 /* 6.1.3 */
1518 /* AUTHOR */
1519 /* */
1520 /* Yuxin Zhou, Microsoft Corporation */
1521 /* */
1522 /* DESCRIPTION */
1523 /* */
1524 /* This function checks for errors on the PTP client create service. */
1525 /* */
1526 /* INPUT */
1527 /* */
1528 /* client_ptr Pointer to PTP client */
1529 /* ip_ptr Pointer to client IP instance */
1530 /* interface_index Index of PTP network interface*/
1531 /* packet_pool_ptr Pointer to client packet pool */
1532 /* thread_priority Priority of PTP thread */
1533 /* thread_stack Pointer to thread stack */
1534 /* stack_size Size of thread stack */
1535 /* clock_callback PTP clock callback */
1536 /* clock_callback_data Data for the clock callback */
1537 /* */
1538 /* OUTPUT */
1539 /* */
1540 /* status Completion status */
1541 /* */
1542 /* CALLS */
1543 /* */
1544 /* _nx_ptp_client_create Actual create service */
1545 /* */
1546 /* CALLED BY */
1547 /* */
1548 /* Application */
1549 /* */
1550 /* RELEASE HISTORY */
1551 /* */
1552 /* DATE NAME DESCRIPTION */
1553 /* */
1554 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1555 /* */
1556 /**************************************************************************/
_nxe_ptp_client_create(NX_PTP_CLIENT * client_ptr,NX_IP * ip_ptr,UINT interface_index,NX_PACKET_POOL * packet_pool_ptr,UINT thread_priority,UCHAR * thread_stack,UINT stack_size,NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback,VOID * clock_callback_data)1557 UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
1558 NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
1559 NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
1560 {
1561
1562 /* Check input parameters. */
1563 if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) ||
1564 (thread_stack == NX_NULL) || (stack_size == 0) || (clock_callback == NX_NULL))
1565 {
1566
1567 /* Return error status. */
1568 return(NX_PTR_ERROR);
1569 }
1570
1571 /* Check for invalid network interface input. */
1572 if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
1573 {
1574 return(NX_INVALID_INTERFACE);
1575 }
1576
1577 /* Check for appropriate caller. */
1578 NX_THREADS_ONLY_CALLER_CHECKING
1579
1580 /* Call the actual function. */
1581 return _nx_ptp_client_create(client_ptr, ip_ptr, interface_index, packet_pool_ptr, thread_priority,
1582 thread_stack, stack_size, clock_callback, clock_callback_data);
1583 }
1584
1585
1586 /**************************************************************************/
1587 /* */
1588 /* FUNCTION RELEASE */
1589 /* */
1590 /* _nx_ptp_client_create PORTABLE C */
1591 /* 6.1.3 */
1592 /* AUTHOR */
1593 /* */
1594 /* Yuxin Zhou, Microsoft Corporation */
1595 /* */
1596 /* DESCRIPTION */
1597 /* */
1598 /* This function creates the PTP client. */
1599 /* */
1600 /* INPUT */
1601 /* */
1602 /* client_ptr Pointer to PTP client */
1603 /* ip_ptr Pointer to client IP instance */
1604 /* interface_index Index of PTP network interface*/
1605 /* packet_pool_ptr Pointer to client packet pool */
1606 /* thread_priority Priority of PTP thread */
1607 /* thread_stack Pointer to thread stack */
1608 /* stack_size Size of thread stack */
1609 /* clock_callback PTP clock callback */
1610 /* clock_callback_data Data for the clock callback */
1611 /* */
1612 /* OUTPUT */
1613 /* */
1614 /* status Completion status */
1615 /* */
1616 /* CALLS */
1617 /* */
1618 /* memset Reset memory */
1619 /* [clock_callback] Initialize clock */
1620 /* tx_event_flags_create Create PTP event flags */
1621 /* tx_event_flags_delete Delete PTP event flags */
1622 /* nx_udp_socket_create Create a UDP socket */
1623 /* nx_udp_socket_delete Delete a UDP socket */
1624 /* nx_udp_socket_receive_notify Set UDP receive notify */
1625 /* tx_timer_create Create a timer */
1626 /* tx_timer_delete Delete a timer */
1627 /* */
1628 /* CALLED BY */
1629 /* */
1630 /* Application */
1631 /* */
1632 /* RELEASE HISTORY */
1633 /* */
1634 /* DATE NAME DESCRIPTION */
1635 /* */
1636 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1637 /* */
1638 /**************************************************************************/
_nx_ptp_client_create(NX_PTP_CLIENT * client_ptr,NX_IP * ip_ptr,UINT interface_index,NX_PACKET_POOL * packet_pool_ptr,UINT thread_priority,UCHAR * thread_stack,UINT stack_size,NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback,VOID * clock_callback_data)1639 UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index,
1640 NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size,
1641 NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data)
1642 {
1643 UINT status;
1644
1645 /* Null the members of NX_PTP_CLIENT. */
1646 memset(client_ptr, 0, sizeof(NX_PTP_CLIENT));
1647
1648 /* Set the Client ID to indicate the PTP client thread is ready. */
1649 client_ptr -> nx_ptp_client_id = NX_PTP_CLIENT_ID;
1650
1651 /* Set the IP instance. */
1652 client_ptr -> nx_ptp_client_ip_ptr = ip_ptr;
1653
1654 /* Set the PTP network interface. */
1655 client_ptr -> nx_ptp_client_interface_index = interface_index;
1656
1657 /* Set the packet pool, check for minimal packet size requirement. */
1658 if (packet_pool_ptr -> nx_packet_pool_payload_size <
1659 (NX_UDP_PACKET + NX_PTP_CLIENT_PACKET_DATA_SIZE))
1660 {
1661 return(NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD);
1662 }
1663 client_ptr -> nx_ptp_client_packet_pool_ptr = packet_pool_ptr;
1664
1665 /* Initialize callback function. */
1666 status = clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_INIT, NX_NULL, NX_NULL, clock_callback_data);
1667 if (status)
1668 {
1669
1670 /* Fail to initialize clock in callback function. */
1671 return(NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE);
1672 }
1673
1674 /* Set the PTP clock callback */
1675 client_ptr -> nx_ptp_client_clock_callback = clock_callback;
1676 client_ptr -> nx_ptp_client_clock_callback_data = clock_callback_data;
1677
1678 /* create the internal PTP event flag object. */
1679 status = tx_event_flags_create(&(client_ptr -> nx_ptp_client_events), "NetX PTP event flag");
1680 if (status != TX_SUCCESS)
1681 {
1682 return(status);
1683 }
1684
1685 /* create the general socket */
1686 status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_general_socket,
1687 "NetX PTP Client general socket", NX_IP_NORMAL,
1688 NX_DONT_FRAGMENT, NX_PTP_TIME_TO_LIVE,
1689 NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
1690 if (status != NX_SUCCESS)
1691 {
1692 tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
1693 return(status);
1694 }
1695 client_ptr -> nx_ptp_client_general_socket.nx_udp_socket_reserved_ptr = client_ptr;
1696 nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_general_socket, _nx_ptp_client_socket_receive_notify);
1697
1698 /* create the event socket */
1699 status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_event_socket,
1700 "NetX PTP Client event socket", NX_IP_NORMAL, NX_DONT_FRAGMENT,
1701 NX_PTP_TIME_TO_LIVE,
1702 NX_PTP_CLIENT_MAX_QUEUE_DEPTH);
1703 if (status != NX_SUCCESS)
1704 {
1705 nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
1706 tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
1707 return(status);
1708 }
1709 client_ptr -> nx_ptp_client_event_socket.nx_udp_socket_reserved_ptr = client_ptr;
1710 nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_event_socket, _nx_ptp_client_socket_receive_notify);
1711
1712 /* create the timer */
1713 status = tx_timer_create(&client_ptr -> nx_ptp_client_timer,
1714 "NetX PTP Client timer",
1715 _nx_ptp_client_timer_handler,
1716 (ULONG)client_ptr,
1717 TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
1718 TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND,
1719 TX_NO_ACTIVATE);
1720 if (status != TX_SUCCESS)
1721 {
1722 nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
1723 nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
1724 tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
1725 return(status);
1726 }
1727
1728 /* create the Client thread */
1729 status = tx_thread_create(&client_ptr -> nx_ptp_client_thread,
1730 "NetX PTP Client", _nx_ptp_client_thread_entry,
1731 (ULONG)client_ptr, thread_stack, stack_size,
1732 thread_priority, thread_priority,
1733 NX_PTP_CLIENT_THREAD_TIME_SLICE, TX_DONT_START);
1734 if (status != TX_SUCCESS)
1735 {
1736 nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket);
1737 nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket);
1738 tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
1739 tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
1740 return(status);
1741 }
1742
1743 /* return Success */
1744 return(NX_SUCCESS);
1745 }
1746
1747 /**************************************************************************/
1748 /* */
1749 /* FUNCTION RELEASE */
1750 /* */
1751 /* _nxe_ptp_client_delete PORTABLE C */
1752 /* 6.1.3 */
1753 /* AUTHOR */
1754 /* */
1755 /* Yuxin Zhou, Microsoft Corporation */
1756 /* */
1757 /* DESCRIPTION */
1758 /* */
1759 /* This function checks for errors on the PTP client delete service. */
1760 /* */
1761 /* INPUT */
1762 /* */
1763 /* client_ptr Pointer to PTP client */
1764 /* */
1765 /* OUTPUT */
1766 /* */
1767 /* status Completion status */
1768 /* */
1769 /* CALLS */
1770 /* */
1771 /* _nx_ptp_client_delete Actual delete service */
1772 /* */
1773 /* CALLED BY */
1774 /* */
1775 /* Application */
1776 /* */
1777 /* RELEASE HISTORY */
1778 /* */
1779 /* DATE NAME DESCRIPTION */
1780 /* */
1781 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1782 /* */
1783 /**************************************************************************/
_nxe_ptp_client_delete(NX_PTP_CLIENT * client_ptr)1784 UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
1785 {
1786
1787 /* Check input parameters. */
1788 if (client_ptr == NX_NULL)
1789 {
1790
1791 /* Return error status. */
1792 return(NX_PTR_ERROR);
1793 }
1794
1795 /* Check for appropriate caller. */
1796 NX_THREADS_ONLY_CALLER_CHECKING
1797
1798 /* Call the actual function. */
1799 return(_nx_ptp_client_delete(client_ptr));
1800 }
1801
1802
1803 /**************************************************************************/
1804 /* */
1805 /* FUNCTION RELEASE */
1806 /* */
1807 /* _nx_ptp_client_delete PORTABLE C */
1808 /* 6.1.3 */
1809 /* AUTHOR */
1810 /* */
1811 /* Yuxin Zhou, Microsoft Corporation */
1812 /* */
1813 /* DESCRIPTION */
1814 /* */
1815 /* This function deletes the PTP client. */
1816 /* */
1817 /* INPUT */
1818 /* */
1819 /* client_ptr Pointer to PTP client */
1820 /* */
1821 /* OUTPUT */
1822 /* */
1823 /* status Completion status */
1824 /* */
1825 /* CALLS */
1826 /* */
1827 /* _nx_ptp_client_stop Stop PTP service */
1828 /* tx_thread_suspend Suspend PTP thread */
1829 /* tx_thread_terminate Terminate PTP thread */
1830 /* tx_thread_delete Delete PTP thread */
1831 /* tx_event_flags_delete Delete PTP event flags */
1832 /* nx_udp_socket_delete Delete a UDP socket */
1833 /* tx_timer_delete Delete a timer */
1834 /* */
1835 /* CALLED BY */
1836 /* */
1837 /* Application */
1838 /* */
1839 /* RELEASE HISTORY */
1840 /* */
1841 /* DATE NAME DESCRIPTION */
1842 /* */
1843 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1844 /* */
1845 /**************************************************************************/
_nx_ptp_client_delete(NX_PTP_CLIENT * client_ptr)1846 UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr)
1847 {
1848
1849 /* Ensure the Client is stopped */
1850 _nx_ptp_client_stop(client_ptr);
1851
1852 /* Suspend the Client thread. */
1853 tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
1854
1855 /* Terminate Client thread. */
1856 tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
1857
1858 /* Delete Client thread. */
1859 tx_thread_delete(&client_ptr -> nx_ptp_client_thread);
1860
1861 /* Delete the timer */
1862 tx_timer_delete(&client_ptr -> nx_ptp_client_timer);
1863
1864 /* Delete the general socket */
1865 nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
1866
1867 /* Delete the event socket */
1868 nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
1869
1870 /* Delete the event flag */
1871 tx_event_flags_delete(&client_ptr -> nx_ptp_client_events);
1872
1873 /* return Success */
1874 return(NX_SUCCESS);
1875 }
1876
1877
1878 /**************************************************************************/
1879 /* */
1880 /* FUNCTION RELEASE */
1881 /* */
1882 /* _nxe_ptp_client_start PORTABLE C */
1883 /* 6.1.3 */
1884 /* AUTHOR */
1885 /* */
1886 /* Yuxin Zhou, Microsoft Corporation */
1887 /* */
1888 /* DESCRIPTION */
1889 /* */
1890 /* This function checks for errors on the PTP client start service. */
1891 /* */
1892 /* INPUT */
1893 /* */
1894 /* client_ptr Pointer to PTP client */
1895 /* client_port_identity_ptr Pointer to client port and */
1896 /* identity */
1897 /* client_port_identity_length Length of client port and */
1898 /* identity */
1899 /* domain PTP clock domain */
1900 /* transport_specific Transport specific */
1901 /* event_callback Event callback */
1902 /* event_callback_data Data for the event callback */
1903 /* */
1904 /* OUTPUT */
1905 /* */
1906 /* status Completion status */
1907 /* */
1908 /* CALLS */
1909 /* */
1910 /* _nx_ptp_client_start Actual start service */
1911 /* */
1912 /* CALLED BY */
1913 /* */
1914 /* Application */
1915 /* */
1916 /* RELEASE HISTORY */
1917 /* */
1918 /* DATE NAME DESCRIPTION */
1919 /* */
1920 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
1921 /* */
1922 /**************************************************************************/
_nxe_ptp_client_start(NX_PTP_CLIENT * client_ptr,UCHAR * client_port_identity_ptr,UINT client_port_identity_length,UINT domain,UINT transport_specific,NX_PTP_CLIENT_EVENT_CALLBACK event_callback,VOID * event_callback_data)1923 UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
1924 UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
1925 VOID *event_callback_data)
1926 {
1927
1928 /* Check input parameters. */
1929 if ((client_ptr == NX_NULL) ||
1930 ((client_port_identity_ptr == NX_NULL) && (client_port_identity_length != 0)) ||
1931 ((client_port_identity_ptr != NX_NULL) && (client_port_identity_length != NX_PTP_CLOCK_PORT_IDENTITY_SIZE)))
1932 {
1933
1934 /* Return error status. */
1935 return(NX_PTR_ERROR);
1936 }
1937
1938 /* Check for appropriate caller. */
1939 NX_THREADS_ONLY_CALLER_CHECKING
1940
1941 /* Call the actual function. */
1942 return(_nx_ptp_client_start(client_ptr, client_port_identity_ptr, client_port_identity_length,
1943 domain, transport_specific, event_callback, event_callback_data));
1944 }
1945
1946
1947 /**************************************************************************/
1948 /* */
1949 /* FUNCTION RELEASE */
1950 /* */
1951 /* _nx_ptp_client_start PORTABLE C */
1952 /* 6.1.3 */
1953 /* AUTHOR */
1954 /* */
1955 /* Yuxin Zhou, Microsoft Corporation */
1956 /* */
1957 /* DESCRIPTION */
1958 /* */
1959 /* This function starts the PTP client. */
1960 /* */
1961 /* INPUT */
1962 /* */
1963 /* client_ptr Pointer to PTP client */
1964 /* client_port_identity_ptr Pointer to client port and */
1965 /* identity */
1966 /* client_port_identity_length Length of client port and */
1967 /* identity */
1968 /* domain PTP clock domain */
1969 /* transport_specific Transport specific */
1970 /* event_callback Event callback */
1971 /* event_callback_data Data for the event callback */
1972 /* */
1973 /* OUTPUT */
1974 /* */
1975 /* status Completion status */
1976 /* */
1977 /* CALLS */
1978 /* */
1979 /* tx_thread_suspend Suspend PTP thread */
1980 /* tx_thread_terminate Terminate PTP thread */
1981 /* tx_thread_reset Reset PTP thread */
1982 /* tx_thread_resume Resume PTP thread */
1983 /* memcpy Copy memory */
1984 /* nx_ip_interface_physical_address_get Get physical address */
1985 /* nx_udp_socket_bind Bind UDP port */
1986 /* nx_ipv4_multicast_interface_join Join IPv4 multicast group */
1987 /* nxd_ipv6_multicast_interface_join Join IPv6 multicast group */
1988 /* tx_timer_activate Activate timer */
1989 /* _nx_ptp_client_stop Stop PTP service */
1990 /* */
1991 /* CALLED BY */
1992 /* */
1993 /* Application */
1994 /* */
1995 /* RELEASE HISTORY */
1996 /* */
1997 /* DATE NAME DESCRIPTION */
1998 /* */
1999 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2000 /* */
2001 /**************************************************************************/
_nx_ptp_client_start(NX_PTP_CLIENT * client_ptr,UCHAR * client_port_identity_ptr,UINT client_port_identity_length,UINT domain,UINT transport_specific,NX_PTP_CLIENT_EVENT_CALLBACK event_callback,VOID * event_callback_data)2002 UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length,
2003 UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback,
2004 VOID *event_callback_data)
2005 {
2006 TX_INTERRUPT_SAVE_AREA
2007 UINT state;
2008 UINT status;
2009 ULONG msw, lsw;
2010 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2011 NXD_ADDRESS maddr;
2012 #endif
2013
2014 NX_PARAMETER_NOT_USED(client_port_identity_length);
2015
2016 /* Check if Client is running */
2017 TX_DISABLE
2018 state = client_ptr -> nx_ptp_client_thread_state;
2019 if (state == NX_PTP_CLIENT_THREAD_IDLE)
2020 {
2021 client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_RUNNING;
2022 }
2023 TX_RESTORE
2024 if (state != NX_PTP_CLIENT_THREAD_IDLE)
2025 {
2026
2027 /* Client is already running */
2028 return(NX_PTP_CLIENT_ALREADY_STARTED);
2029 }
2030
2031 /* ensure the thread is terminated */
2032 tx_thread_suspend(&client_ptr -> nx_ptp_client_thread);
2033 tx_thread_terminate(&client_ptr -> nx_ptp_client_thread);
2034
2035 /* save the client parameters */
2036 client_ptr -> nx_ptp_client_domain = (UCHAR)domain;
2037 client_ptr -> nx_ptp_client_transport_specific = (UCHAR)transport_specific;
2038 client_ptr -> nx_ptp_client_event_callback = event_callback;
2039 client_ptr -> nx_ptp_client_event_callback_data = event_callback_data;
2040
2041 /* reset and resume the thread */
2042 status = tx_thread_reset(&client_ptr -> nx_ptp_client_thread);
2043 if (status != TX_SUCCESS)
2044 {
2045 TX_DISABLE
2046 client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
2047 TX_RESTORE
2048
2049 return(status);
2050 }
2051 tx_thread_resume(&client_ptr -> nx_ptp_client_thread);
2052
2053 /* set the client port and identity */
2054 if (client_port_identity_ptr != NX_NULL)
2055 {
2056
2057 /* copy provided identifier */
2058 memcpy(client_ptr -> nx_ptp_client_port_identity, client_port_identity_ptr,
2059 NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */
2060 }
2061 else
2062 {
2063
2064 /* get MAC address of interface */
2065 status = nx_ip_interface_physical_address_get(client_ptr -> nx_ptp_client_ip_ptr,
2066 client_ptr -> nx_ptp_client_interface_index,
2067 &msw, &lsw);
2068 if (status == TX_SUCCESS)
2069 {
2070 /* convert 48-bit MAC address to 64-bit EUI */
2071 client_ptr -> nx_ptp_client_port_identity[0] = (UCHAR)(msw >> 8);
2072 client_ptr -> nx_ptp_client_port_identity[1] = (UCHAR)msw;
2073 client_ptr -> nx_ptp_client_port_identity[2] = (UCHAR)(lsw >> 24);
2074 client_ptr -> nx_ptp_client_port_identity[3] = 0xff;
2075 client_ptr -> nx_ptp_client_port_identity[4] = 0xfe;
2076 client_ptr -> nx_ptp_client_port_identity[5] = (UCHAR)(lsw >> 16);
2077 client_ptr -> nx_ptp_client_port_identity[6] = (UCHAR)(lsw >> 8);
2078 client_ptr -> nx_ptp_client_port_identity[7] = (UCHAR)lsw;
2079
2080 /* set default port number (1) */
2081 client_ptr -> nx_ptp_client_port_identity[8] = 0;
2082 client_ptr -> nx_ptp_client_port_identity[9] = 1;
2083 }
2084 }
2085
2086 /* bind the general socket */
2087 if (status == TX_SUCCESS)
2088 {
2089 status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket,
2090 NX_PTP_GENERAL_UDP_PORT, NX_NO_WAIT);
2091 }
2092
2093 /* bind the event socket */
2094 if (status == TX_SUCCESS)
2095 {
2096 status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket,
2097 NX_PTP_EVENT_UDP_PORT, NX_NO_WAIT);
2098 }
2099
2100 /* join the multicast groups */
2101 if (status == TX_SUCCESS)
2102 {
2103 status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
2104 NX_PTP_IPV4_MULTICAST_ADDR,
2105 client_ptr -> nx_ptp_client_interface_index);
2106 if (status == TX_SUCCESS)
2107 {
2108 client_ptr -> nx_ptp_client_ipv4_group_joined = NX_TRUE;
2109 }
2110 }
2111 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2112 if (status == TX_SUCCESS)
2113 {
2114 NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
2115 status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr,
2116 &maddr, client_ptr -> nx_ptp_client_interface_index);
2117 if (status == TX_SUCCESS)
2118 {
2119 client_ptr -> nx_ptp_client_ipv6_group_joined = NX_TRUE;
2120 }
2121 else if ((status == NX_NOT_SUPPORTED) && (client_ptr -> nx_ptp_client_ipv4_group_joined))
2122 {
2123
2124 /* IPv6 not enabled, use IPv4 only */
2125 status = TX_SUCCESS;
2126 }
2127 }
2128 #endif
2129
2130 /* activate the Client timer */
2131 if (status == TX_SUCCESS)
2132 {
2133
2134 /* activate the timer */
2135 status = tx_timer_activate(&client_ptr -> nx_ptp_client_timer);
2136 }
2137
2138 /* stop the client thread in case of error */
2139 if (status != TX_SUCCESS)
2140 {
2141 _nx_ptp_client_stop(client_ptr);
2142
2143 /* return failure */
2144 return(status);
2145 }
2146
2147 /* return Success */
2148 return(NX_SUCCESS);
2149 }
2150
2151
2152 /**************************************************************************/
2153 /* */
2154 /* FUNCTION RELEASE */
2155 /* */
2156 /* _nxe_ptp_client_stop PORTABLE C */
2157 /* 6.1.3 */
2158 /* AUTHOR */
2159 /* */
2160 /* Yuxin Zhou, Microsoft Corporation */
2161 /* */
2162 /* DESCRIPTION */
2163 /* */
2164 /* This function checks for errors on the PTP client stop service. */
2165 /* */
2166 /* INPUT */
2167 /* */
2168 /* client_ptr Pointer to PTP client */
2169 /* */
2170 /* OUTPUT */
2171 /* */
2172 /* status Completion status */
2173 /* */
2174 /* CALLS */
2175 /* */
2176 /* _nx_ptp_client_stop Actual stop service */
2177 /* */
2178 /* CALLED BY */
2179 /* */
2180 /* Application */
2181 /* */
2182 /* RELEASE HISTORY */
2183 /* */
2184 /* DATE NAME DESCRIPTION */
2185 /* */
2186 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2187 /* */
2188 /**************************************************************************/
_nxe_ptp_client_stop(NX_PTP_CLIENT * client_ptr)2189 UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
2190 {
2191
2192 /* Check input parameters. */
2193 if (client_ptr == NX_NULL)
2194 {
2195
2196 /* Return error status. */
2197 return(NX_PTR_ERROR);
2198 }
2199
2200 /* Check for appropriate caller. */
2201 NX_THREADS_ONLY_CALLER_CHECKING
2202
2203 /* Call the actual function. */
2204 return(_nx_ptp_client_stop(client_ptr));
2205 }
2206
2207
2208 /**************************************************************************/
2209 /* */
2210 /* FUNCTION RELEASE */
2211 /* */
2212 /* _nx_ptp_client_stop PORTABLE C */
2213 /* 6.1.3 */
2214 /* AUTHOR */
2215 /* */
2216 /* Yuxin Zhou, Microsoft Corporation */
2217 /* */
2218 /* DESCRIPTION */
2219 /* */
2220 /* This function stops the PTP client. */
2221 /* */
2222 /* INPUT */
2223 /* */
2224 /* client_ptr Pointer to PTP client */
2225 /* */
2226 /* OUTPUT */
2227 /* */
2228 /* status Completion status */
2229 /* */
2230 /* CALLS */
2231 /* */
2232 /* tx_timer_deactivate Deactivate timer */
2233 /* nx_udp_socket_unbind Unbind UDP port */
2234 /* nx_ipv4_multicast_interface_leave Leave IPv4 multicast group */
2235 /* nxd_ipv6_multicast_interface_leave Leave IPv6 multicast group */
2236 /* tx_event_flags_set Set PTP timer event */
2237 /* tx_thread_sleep Thread sleep */
2238 /* */
2239 /* CALLED BY */
2240 /* */
2241 /* Application */
2242 /* */
2243 /* RELEASE HISTORY */
2244 /* */
2245 /* DATE NAME DESCRIPTION */
2246 /* */
2247 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2248 /* */
2249 /**************************************************************************/
_nx_ptp_client_stop(NX_PTP_CLIENT * client_ptr)2250 UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr)
2251 {
2252 TX_INTERRUPT_SAVE_AREA
2253 UINT state;
2254 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2255 NXD_ADDRESS maddr;
2256 #endif
2257
2258 /* Check if Client is running */
2259 TX_DISABLE
2260 state = client_ptr -> nx_ptp_client_thread_state;
2261 if (state == NX_PTP_CLIENT_THREAD_RUNNING)
2262 {
2263 client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPING;
2264 }
2265 TX_RESTORE
2266 if ((state != NX_PTP_CLIENT_THREAD_RUNNING) &&
2267 (state != NX_PTP_CLIENT_THREAD_STOPPED))
2268 {
2269
2270 /* Client is not running */
2271 return(NX_PTP_CLIENT_NOT_STARTED);
2272 }
2273
2274 /* deactivate the timer */
2275 tx_timer_deactivate(&client_ptr -> nx_ptp_client_timer);
2276
2277 /* unbind the sockets */
2278 nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket);
2279 nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket);
2280
2281 /* leave multicast groups */
2282 if (client_ptr -> nx_ptp_client_ipv4_group_joined)
2283 {
2284 nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
2285 NX_PTP_IPV4_MULTICAST_ADDR,
2286 client_ptr -> nx_ptp_client_interface_index);
2287 client_ptr -> nx_ptp_client_ipv4_group_joined = NX_FALSE;
2288 }
2289 #if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6)
2290 if (client_ptr -> nx_ptp_client_ipv6_group_joined)
2291 {
2292 NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr);
2293 nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr,
2294 &maddr, client_ptr -> nx_ptp_client_interface_index);
2295 client_ptr -> nx_ptp_client_ipv6_group_joined = NX_FALSE;
2296 }
2297 #endif
2298
2299 /* send STOP message */
2300 tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_STOP_EVENT, TX_OR);
2301
2302 /* wait for thread termination */
2303 while (state != NX_PTP_CLIENT_THREAD_STOPPED)
2304 {
2305 tx_thread_sleep(1);
2306 TX_DISABLE
2307 state = client_ptr -> nx_ptp_client_thread_state;
2308 TX_RESTORE
2309 }
2310
2311 /* set Idle state */
2312 TX_DISABLE
2313 client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE;
2314 TX_RESTORE
2315
2316 /* return Success */
2317 return(NX_SUCCESS);
2318 }
2319
2320
2321 /**************************************************************************/
2322 /* */
2323 /* FUNCTION RELEASE */
2324 /* */
2325 /* _nxe_ptp_client_time_get PORTABLE C */
2326 /* 6.1.3 */
2327 /* AUTHOR */
2328 /* */
2329 /* Yuxin Zhou, Microsoft Corporation */
2330 /* */
2331 /* DESCRIPTION */
2332 /* */
2333 /* This function checks for errors on the PTP time get service. */
2334 /* */
2335 /* INPUT */
2336 /* */
2337 /* client_ptr Pointer to PTP client */
2338 /* time_ptr Pointer to PTP time */
2339 /* */
2340 /* OUTPUT */
2341 /* */
2342 /* status Completion status */
2343 /* */
2344 /* CALLS */
2345 /* */
2346 /* _nx_ptp_client_time_get Actual time get service */
2347 /* */
2348 /* CALLED BY */
2349 /* */
2350 /* Application */
2351 /* */
2352 /* RELEASE HISTORY */
2353 /* */
2354 /* DATE NAME DESCRIPTION */
2355 /* */
2356 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2357 /* */
2358 /**************************************************************************/
_nxe_ptp_client_time_get(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * time_ptr)2359 UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
2360 {
2361
2362 /* Check input parameters. */
2363 if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
2364 {
2365
2366 /* Return error status. */
2367 return(NX_PTR_ERROR);
2368 }
2369
2370 /* Check for appropriate caller. */
2371 NX_THREADS_ONLY_CALLER_CHECKING
2372
2373 /* Call the actual function. */
2374 return(_nx_ptp_client_time_get(client_ptr, time_ptr));
2375 }
2376
2377
2378 /**************************************************************************/
2379 /* */
2380 /* FUNCTION RELEASE */
2381 /* */
2382 /* _nx_ptp_client_time_get PORTABLE C */
2383 /* 6.1.3 */
2384 /* AUTHOR */
2385 /* */
2386 /* Yuxin Zhou, Microsoft Corporation */
2387 /* */
2388 /* DESCRIPTION */
2389 /* */
2390 /* This function gets the current value of the PTP clock. */
2391 /* */
2392 /* INPUT */
2393 /* */
2394 /* client_ptr Pointer to PTP client */
2395 /* time_ptr Pointer to PTP time */
2396 /* */
2397 /* OUTPUT */
2398 /* */
2399 /* status Completion status */
2400 /* */
2401 /* CALLS */
2402 /* */
2403 /* None */
2404 /* */
2405 /* CALLED BY */
2406 /* */
2407 /* Application */
2408 /* */
2409 /* RELEASE HISTORY */
2410 /* */
2411 /* DATE NAME DESCRIPTION */
2412 /* */
2413 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2414 /* */
2415 /**************************************************************************/
_nx_ptp_client_time_get(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * time_ptr)2416 UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
2417 {
2418
2419 /* Get the current PTP clock */
2420 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET,
2421 time_ptr, NX_NULL,
2422 client_ptr -> nx_ptp_client_clock_callback_data);
2423
2424 /* return Success */
2425 return(NX_SUCCESS);
2426 }
2427
2428
2429 /**************************************************************************/
2430 /* */
2431 /* FUNCTION RELEASE */
2432 /* */
2433 /* _nxe_ptp_client_time_set PORTABLE C */
2434 /* 6.1.3 */
2435 /* AUTHOR */
2436 /* */
2437 /* Yuxin Zhou, Microsoft Corporation */
2438 /* */
2439 /* DESCRIPTION */
2440 /* */
2441 /* This function checks for errors on the PTP time set service. */
2442 /* */
2443 /* INPUT */
2444 /* */
2445 /* client_ptr Pointer to PTP client */
2446 /* time_ptr Pointer to PTP time */
2447 /* */
2448 /* OUTPUT */
2449 /* */
2450 /* status Completion status */
2451 /* */
2452 /* CALLS */
2453 /* */
2454 /* _nx_ptp_client_time_set Actual time set service */
2455 /* */
2456 /* CALLED BY */
2457 /* */
2458 /* Application */
2459 /* */
2460 /* RELEASE HISTORY */
2461 /* */
2462 /* DATE NAME DESCRIPTION */
2463 /* */
2464 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2465 /* */
2466 /**************************************************************************/
_nxe_ptp_client_time_set(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * time_ptr)2467 UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
2468 {
2469
2470 /* Check input parameters. */
2471 if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL))
2472 {
2473
2474 /* Return error status. */
2475 return(NX_PTR_ERROR);
2476 }
2477
2478 /* Check for appropriate caller. */
2479 NX_THREADS_ONLY_CALLER_CHECKING
2480
2481 /* Call the actual function. */
2482 return(_nx_ptp_client_time_set(client_ptr, time_ptr));
2483 }
2484
2485
2486 /**************************************************************************/
2487 /* */
2488 /* FUNCTION RELEASE */
2489 /* */
2490 /* _nx_ptp_client_time_set PORTABLE C */
2491 /* 6.1.3 */
2492 /* AUTHOR */
2493 /* */
2494 /* Yuxin Zhou, Microsoft Corporation */
2495 /* */
2496 /* DESCRIPTION */
2497 /* */
2498 /* This function sets the initial time of the PTP clock. */
2499 /* */
2500 /* INPUT */
2501 /* */
2502 /* client_ptr Pointer to PTP client */
2503 /* time_ptr Pointer to PTP time */
2504 /* */
2505 /* OUTPUT */
2506 /* */
2507 /* status Completion status */
2508 /* */
2509 /* CALLS */
2510 /* */
2511 /* None */
2512 /* */
2513 /* CALLED BY */
2514 /* */
2515 /* Application */
2516 /* */
2517 /* RELEASE HISTORY */
2518 /* */
2519 /* DATE NAME DESCRIPTION */
2520 /* */
2521 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2522 /* */
2523 /**************************************************************************/
_nx_ptp_client_time_set(NX_PTP_CLIENT * client_ptr,NX_PTP_TIME * time_ptr)2524 UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr)
2525 {
2526 TX_INTERRUPT_SAVE_AREA
2527 UINT state;
2528
2529 /* Check if Client is running */
2530 TX_DISABLE
2531 state = client_ptr -> nx_ptp_client_thread_state;
2532 TX_RESTORE
2533
2534 if (state != NX_PTP_CLIENT_THREAD_IDLE)
2535 {
2536
2537 /* Cannot set the clock when the client is running */
2538 return(NX_PTP_CLIENT_ALREADY_STARTED);
2539 }
2540
2541 /* Set the current PTP clock */
2542 client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET,
2543 time_ptr, NX_NULL,
2544 client_ptr -> nx_ptp_client_clock_callback_data);
2545
2546 /* return Success */
2547 return(NX_SUCCESS);
2548 }
2549
2550
2551 /**************************************************************************/
2552 /* */
2553 /* FUNCTION RELEASE */
2554 /* */
2555 /* _nxe_ptp_client_master_info_get PORTABLE C */
2556 /* 6.1.3 */
2557 /* AUTHOR */
2558 /* */
2559 /* Yuxin Zhou, Microsoft Corporation */
2560 /* */
2561 /* DESCRIPTION */
2562 /* */
2563 /* This function checks for errors on the PTP master info get service. */
2564 /* */
2565 /* INPUT */
2566 /* */
2567 /* master_ptr Pointer to PTP master clock */
2568 /* address Address of master clock */
2569 /* port_identity PTP master port and identity */
2570 /* port_identity_length Length of PTP master port and */
2571 /* identity */
2572 /* priority1 Priority1 of PTP master clock */
2573 /* priority2 Priority2 of PTP master clock */
2574 /* clock_class Class of PTP master clock */
2575 /* clock_accuracy Accuracy of PTP master clock */
2576 /* clock_variance Variance of PTP master clock */
2577 /* grandmaster_identity Identity of grandmaster clock */
2578 /* grandmaster_identity_length Length of grandmaster Identity*/
2579 /* steps_removed Steps removed from PTP header */
2580 /* time_source The source of timer used by */
2581 /* grandmaster clock */
2582 /* */
2583 /* OUTPUT */
2584 /* */
2585 /* status Completion status */
2586 /* */
2587 /* CALLS */
2588 /* */
2589 /* _nx_ptp_client_master_info_get Actual master info get service*/
2590 /* */
2591 /* CALLED BY */
2592 /* */
2593 /* Application */
2594 /* */
2595 /* RELEASE HISTORY */
2596 /* */
2597 /* DATE NAME DESCRIPTION */
2598 /* */
2599 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2600 /* */
2601 /**************************************************************************/
_nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER * master_ptr,NXD_ADDRESS * address,UCHAR ** port_identity,UINT * port_identity_length,UCHAR * priority1,UCHAR * priority2,UCHAR * clock_class,UCHAR * clock_accuracy,USHORT * clock_variance,UCHAR ** grandmaster_identity,UINT * grandmaster_identity_length,USHORT * steps_removed,UCHAR * time_source)2602 UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
2603 UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
2604 UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
2605 UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
2606 {
2607 if (master_ptr == NX_NULL)
2608 {
2609
2610 /* Return error status. */
2611 return(NX_PTR_ERROR);
2612 }
2613
2614 /* Check for appropriate caller. */
2615 NX_THREADS_ONLY_CALLER_CHECKING
2616
2617 return(_nx_ptp_client_master_info_get(master_ptr, address, port_identity, port_identity_length, priority1,
2618 priority2, clock_class, clock_accuracy, clock_variance, grandmaster_identity,
2619 grandmaster_identity_length, steps_removed, time_source));
2620 }
2621
2622
2623 /**************************************************************************/
2624 /* */
2625 /* FUNCTION RELEASE */
2626 /* */
2627 /* _nx_ptp_client_master_info_get PORTABLE C */
2628 /* 6.1.3 */
2629 /* AUTHOR */
2630 /* */
2631 /* Yuxin Zhou, Microsoft Corporation */
2632 /* */
2633 /* DESCRIPTION */
2634 /* */
2635 /* This function gets information of master clock. */
2636 /* */
2637 /* INPUT */
2638 /* */
2639 /* master_ptr Pointer to PTP master clock */
2640 /* address Address of master clock */
2641 /* port_identity PTP master port and identity */
2642 /* port_identity_length Length of PTP master port and */
2643 /* identity */
2644 /* priority1 Priority1 of PTP master clock */
2645 /* priority2 Priority2 of PTP master clock */
2646 /* clock_class Class of PTP master clock */
2647 /* clock_accuracy Accuracy of PTP master clock */
2648 /* clock_variance Variance of PTP master clock */
2649 /* grandmaster_identity Identity of grandmaster clock */
2650 /* grandmaster_identity_length Length of grandmaster Identity*/
2651 /* steps_removed Steps removed from PTP header */
2652 /* time_source The source of timer used by */
2653 /* grandmaster clock */
2654 /* */
2655 /* OUTPUT */
2656 /* */
2657 /* status Completion status */
2658 /* */
2659 /* CALLS */
2660 /* */
2661 /* None */
2662 /* */
2663 /* CALLED BY */
2664 /* */
2665 /* Application */
2666 /* */
2667 /* RELEASE HISTORY */
2668 /* */
2669 /* DATE NAME DESCRIPTION */
2670 /* */
2671 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2672 /* */
2673 /**************************************************************************/
_nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER * master_ptr,NXD_ADDRESS * address,UCHAR ** port_identity,UINT * port_identity_length,UCHAR * priority1,UCHAR * priority2,UCHAR * clock_class,UCHAR * clock_accuracy,USHORT * clock_variance,UCHAR ** grandmaster_identity,UINT * grandmaster_identity_length,USHORT * steps_removed,UCHAR * time_source)2674 UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity,
2675 UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class,
2676 UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity,
2677 UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source)
2678 {
2679
2680 /* Set master information when the output pointer is provided. */
2681 if (address)
2682 {
2683 *address = *(master_ptr -> nx_ptp_client_master_address);
2684 }
2685
2686 if (port_identity && port_identity_length)
2687 {
2688 *port_identity = master_ptr -> nx_ptp_client_master_port_identity;
2689 *port_identity_length = NX_PTP_CLOCK_PORT_IDENTITY_SIZE;
2690 }
2691
2692 if (priority1)
2693 {
2694 *priority1 = master_ptr -> nx_ptp_client_master_priority1;
2695 }
2696
2697 if (priority2)
2698 {
2699 *priority2 = master_ptr -> nx_ptp_client_master_priority2;
2700 }
2701
2702 if (clock_class)
2703 {
2704 *clock_class = master_ptr -> nx_ptp_client_master_clock_class;
2705 }
2706
2707 if (clock_accuracy)
2708 {
2709 *clock_accuracy = master_ptr -> nx_ptp_client_master_clock_accuracy;
2710 }
2711
2712 if (clock_variance)
2713 {
2714 *clock_variance = master_ptr -> nx_ptp_client_master_offset_scaled_log_variance;
2715 }
2716
2717 if (grandmaster_identity && grandmaster_identity_length)
2718 {
2719 *grandmaster_identity = master_ptr -> nx_ptp_client_master_grandmaster_identity;
2720 *grandmaster_identity_length = NX_PTP_CLOCK_IDENTITY_SIZE;
2721 }
2722
2723 if (steps_removed)
2724 {
2725 *steps_removed = master_ptr -> nx_ptp_client_master_steps_removed;
2726 }
2727
2728 if (time_source)
2729 {
2730 *time_source = master_ptr -> nx_ptp_client_master_time_source;
2731 }
2732
2733 return(NX_SUCCESS);
2734 }
2735
2736
2737 /**************************************************************************/
2738 /* */
2739 /* FUNCTION RELEASE */
2740 /* */
2741 /* _nxe_ptp_client_sync_info_get PORTABLE C */
2742 /* 6.1.3 */
2743 /* AUTHOR */
2744 /* */
2745 /* Yuxin Zhou, Microsoft Corporation */
2746 /* */
2747 /* DESCRIPTION */
2748 /* */
2749 /* This function checks for errors on the PTP Sync get service. */
2750 /* */
2751 /* INPUT */
2752 /* */
2753 /* client_ptr Pointer to PTP client */
2754 /* flags Flags in Sync message */
2755 /* utc_offset Offset between TAI and UTC */
2756 /* */
2757 /* OUTPUT */
2758 /* */
2759 /* status Completion status */
2760 /* */
2761 /* CALLS */
2762 /* */
2763 /* _nx_ptp_client_sync_info_get Actual Sync info get service */
2764 /* */
2765 /* CALLED BY */
2766 /* */
2767 /* Application */
2768 /* */
2769 /* RELEASE HISTORY */
2770 /* */
2771 /* DATE NAME DESCRIPTION */
2772 /* */
2773 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2774 /* */
2775 /**************************************************************************/
_nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC * sync_ptr,USHORT * flags,SHORT * utc_offset)2776 UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
2777 {
2778 if (sync_ptr == NX_NULL)
2779 {
2780
2781 /* Return error status. */
2782 return(NX_PTR_ERROR);
2783 }
2784
2785 /* Check for appropriate caller. */
2786 NX_THREADS_ONLY_CALLER_CHECKING
2787
2788 return(_nx_ptp_client_sync_info_get(sync_ptr, flags, utc_offset));
2789 }
2790
2791
2792 /**************************************************************************/
2793 /* */
2794 /* FUNCTION RELEASE */
2795 /* */
2796 /* _nx_ptp_client_sync_info_get PORTABLE C */
2797 /* 6.1.3 */
2798 /* AUTHOR */
2799 /* */
2800 /* Yuxin Zhou, Microsoft Corporation */
2801 /* */
2802 /* DESCRIPTION */
2803 /* */
2804 /* This function gets information of Sync message. */
2805 /* */
2806 /* INPUT */
2807 /* */
2808 /* client_ptr Pointer to PTP client */
2809 /* flags Flags in Sync message */
2810 /* utc_offset Offset between TAI and UTC */
2811 /* */
2812 /* OUTPUT */
2813 /* */
2814 /* status Completion status */
2815 /* */
2816 /* CALLS */
2817 /* */
2818 /* None */
2819 /* */
2820 /* CALLED BY */
2821 /* */
2822 /* Application */
2823 /* */
2824 /* RELEASE HISTORY */
2825 /* */
2826 /* DATE NAME DESCRIPTION */
2827 /* */
2828 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2829 /* */
2830 /**************************************************************************/
_nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC * sync_ptr,USHORT * flags,SHORT * utc_offset)2831 UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset)
2832 {
2833
2834 /* Set SYNC information when the output pointer is provided. */
2835 if (flags)
2836 {
2837 *flags = sync_ptr -> nx_ptp_client_sync_flags;
2838 }
2839
2840 if (utc_offset)
2841 {
2842 *utc_offset = sync_ptr -> nx_ptp_client_sync_utc_offset;
2843 }
2844
2845 return(NX_SUCCESS);
2846 }
2847
2848
2849 /**************************************************************************/
2850 /* */
2851 /* FUNCTION RELEASE */
2852 /* */
2853 /* _nx_ptp_client_packet_timestamp_notify PORTABLE C */
2854 /* 6.1.3 */
2855 /* AUTHOR */
2856 /* */
2857 /* Yuxin Zhou, Microsoft Corporation */
2858 /* */
2859 /* DESCRIPTION */
2860 /* */
2861 /* This function notifies the PTP packet is transmitted with timestamp.*/
2862 /* */
2863 /* INPUT */
2864 /* */
2865 /* client_ptr Pointer to PTP client */
2866 /* packet_ptr Pointer to PTP packet */
2867 /* timestamp_ptr Pointer to timestamp */
2868 /* */
2869 /* OUTPUT */
2870 /* */
2871 /* None */
2872 /* */
2873 /* CALLS */
2874 /* */
2875 /* None */
2876 /* */
2877 /* CALLED BY */
2878 /* */
2879 /* Application */
2880 /* */
2881 /* RELEASE HISTORY */
2882 /* */
2883 /* DATE NAME DESCRIPTION */
2884 /* */
2885 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2886 /* */
2887 /**************************************************************************/
_nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT * client_ptr,NX_PACKET * packet_ptr,NX_PTP_TIME * timestamp_ptr)2888 VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr)
2889 {
2890
2891 /* get timestamp of previous delay_req message */
2892 if (client_ptr &&
2893 (client_ptr -> nx_ptp_client_delay_state == NX_PTP_CLIENT_DELAY_WAIT_REQ_TS) &&
2894 (client_ptr -> nx_ptp_client_delay_req_packet_ptr == packet_ptr))
2895 {
2896
2897 /* store timestamp */
2898 client_ptr -> nx_ptp_client_delay_ts = *timestamp_ptr;
2899
2900 /* update state */
2901 client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_RESP;
2902 }
2903 }
2904
2905
2906 /**************************************************************************/
2907 /* */
2908 /* FUNCTION RELEASE */
2909 /* */
2910 /* _nx_ptp_client_soft_clock_callback PORTABLE C */
2911 /* 6.1.3 */
2912 /* AUTHOR */
2913 /* */
2914 /* Yuxin Zhou, Microsoft Corporation */
2915 /* */
2916 /* DESCRIPTION */
2917 /* */
2918 /* This function implements soft PTP clock. */
2919 /* */
2920 /* INPUT */
2921 /* */
2922 /* client_ptr Pointer to PTP client */
2923 /* operation PTP clock operation */
2924 /* time_ptr Pointer to timestamp */
2925 /* packet_ptr Pointer to PTP packet */
2926 /* callback_data Pointer to callback data */
2927 /* */
2928 /* OUTPUT */
2929 /* */
2930 /* status Completion status */
2931 /* */
2932 /* CALLS */
2933 /* */
2934 /* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
2935 /* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
2936 /* */
2937 /* CALLED BY */
2938 /* */
2939 /* PTP internal */
2940 /* */
2941 /* RELEASE HISTORY */
2942 /* */
2943 /* DATE NAME DESCRIPTION */
2944 /* */
2945 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
2946 /* */
2947 /**************************************************************************/
_nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT * client_ptr,UINT operation,NX_PTP_TIME * time_ptr,NX_PACKET * packet_ptr,VOID * callback_data)2948 UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation,
2949 NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
2950 VOID *callback_data)
2951 {
2952 TX_INTERRUPT_SAVE_AREA
2953
2954 NX_PARAMETER_NOT_USED(callback_data);
2955
2956 switch (operation)
2957 {
2958
2959 /* Nothing to do for soft initialization. */
2960 case NX_PTP_CLIENT_CLOCK_INIT:
2961 break;
2962
2963 /* Set clock. */
2964 case NX_PTP_CLIENT_CLOCK_SET:
2965 TX_DISABLE
2966 client_ptr -> nx_ptp_client_soft_clock = *time_ptr;
2967 TX_RESTORE
2968 break;
2969
2970 /* Extract timestamp from packet.
2971 For soft implementation, simply fallthrough and return current timestamp. */
2972 case NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT:
2973
2974 /* Get clock. */
2975 case NX_PTP_CLIENT_CLOCK_GET:
2976 TX_DISABLE
2977 *time_ptr = client_ptr -> nx_ptp_client_soft_clock;
2978 TX_RESTORE
2979 break;
2980
2981 /* Adjust clock. */
2982 case NX_PTP_CLIENT_CLOCK_ADJUST:
2983 _nx_ptp_client_soft_clock_adjust(client_ptr, time_ptr -> nanosecond);
2984 break;
2985
2986 /* Prepare timestamp for current packet.
2987 For soft implementation, simply notify current timestamp. */
2988 case NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE:
2989 _nx_ptp_client_packet_timestamp_notify(client_ptr, packet_ptr, &(client_ptr -> nx_ptp_client_soft_clock));
2990 break;
2991
2992 /* Update soft timer. */
2993 case NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE:
2994 TX_DISABLE
2995
2996 /* increment the nanosecond field of the software clock */
2997 time_ptr -> nanosecond +=
2998 (LONG)(NX_PTP_NANOSECONDS_PER_SEC / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND);
2999
3000 /* update the second field */
3001 if (time_ptr -> nanosecond >= NX_PTP_NANOSECONDS_PER_SEC)
3002 {
3003 time_ptr -> nanosecond -= NX_PTP_NANOSECONDS_PER_SEC;
3004 _nx_ptp_client_utility_inc64(&(time_ptr -> second_high),
3005 &(time_ptr -> second_low));
3006 }
3007 TX_RESTORE
3008 break;
3009
3010 default:
3011 return(NX_PTP_PARAM_ERROR);
3012 }
3013
3014 return(NX_SUCCESS);
3015 }
3016
3017
3018 /**************************************************************************/
3019 /* */
3020 /* FUNCTION RELEASE */
3021 /* */
3022 /* _nxe_ptp_client_utility_time_diff PORTABLE C */
3023 /* 6.1.3 */
3024 /* AUTHOR */
3025 /* */
3026 /* Yuxin Zhou, Microsoft Corporation */
3027 /* */
3028 /* DESCRIPTION */
3029 /* */
3030 /* This function checks for errors on the PTP time difference service. */
3031 /* */
3032 /* INPUT */
3033 /* */
3034 /* time1_ptr Pointer to first PTP time */
3035 /* time2_ptr Pointer to second PTP time */
3036 /* result_ptr Pointer to result time1-time2 */
3037 /* */
3038 /* OUTPUT */
3039 /* */
3040 /* status Completion status */
3041 /* */
3042 /* CALLS */
3043 /* */
3044 /* _nx_ptp_client_utility_time_diff Actual time difference service*/
3045 /* */
3046 /* CALLED BY */
3047 /* */
3048 /* Application */
3049 /* */
3050 /* RELEASE HISTORY */
3051 /* */
3052 /* DATE NAME DESCRIPTION */
3053 /* */
3054 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3055 /* */
3056 /**************************************************************************/
_nxe_ptp_client_utility_time_diff(NX_PTP_TIME * time1_ptr,NX_PTP_TIME * time2_ptr,NX_PTP_TIME * result_ptr)3057 UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
3058 {
3059
3060 /* Check input parameters. */
3061 if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL))
3062 {
3063
3064 /* Return error status. */
3065 return(NX_PTR_ERROR);
3066 }
3067
3068 /* Check for appropriate caller. */
3069 NX_THREADS_ONLY_CALLER_CHECKING
3070
3071 /* Call the actual function. */
3072 return(_nx_ptp_client_utility_time_diff(time1_ptr, time2_ptr, result_ptr));
3073 }
3074
3075
3076 /**************************************************************************/
3077 /* */
3078 /* FUNCTION RELEASE */
3079 /* */
3080 /* _nx_ptp_client_utility_time_diff PORTABLE C */
3081 /* 6.1.3 */
3082 /* AUTHOR */
3083 /* */
3084 /* Yuxin Zhou, Microsoft Corporation */
3085 /* */
3086 /* DESCRIPTION */
3087 /* */
3088 /* This function computes the difference between two PTP times. */
3089 /* */
3090 /* INPUT */
3091 /* */
3092 /* time1_ptr Pointer to first PTP time */
3093 /* time2_ptr Pointer to second PTP time */
3094 /* result_ptr Pointer to result time1-time2 */
3095 /* */
3096 /* OUTPUT */
3097 /* */
3098 /* status Completion status */
3099 /* */
3100 /* CALLS */
3101 /* */
3102 /* _nx_ptp_client_utility_sub64 Subtracts two 64-bit numbers */
3103 /* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */
3104 /* _nx_ptp_client_utility_inc64 Increment a 64-bit number */
3105 /* */
3106 /* CALLED BY */
3107 /* */
3108 /* Application */
3109 /* _nx_ptp_client_delay_resp_received Process delay response */
3110 /* */
3111 /* RELEASE HISTORY */
3112 /* */
3113 /* DATE NAME DESCRIPTION */
3114 /* */
3115 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3116 /* */
3117 /**************************************************************************/
_nx_ptp_client_utility_time_diff(NX_PTP_TIME * time1_ptr,NX_PTP_TIME * time2_ptr,NX_PTP_TIME * result_ptr)3118 UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr)
3119 {
3120 LONG sec_hi;
3121 ULONG sec_lo;
3122 LONG ns;
3123
3124 /* compute difference of seconds */
3125 sec_hi = time1_ptr -> second_high;
3126 sec_lo = time1_ptr -> second_low;
3127 _nx_ptp_client_utility_sub64(&sec_hi, &sec_lo, time2_ptr -> second_high,
3128 time2_ptr -> second_low);
3129
3130 /* compute difference of nanoseconds */
3131 /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */
3132 ns = time1_ptr -> nanosecond - time2_ptr -> nanosecond;
3133
3134 /* keep nanoseconds in range +/-0-999999999 */
3135 if (ns <= -NX_PTP_NANOSECONDS_PER_SEC)
3136 {
3137 ns += NX_PTP_NANOSECONDS_PER_SEC;
3138 _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
3139 }
3140 else if (ns >= NX_PTP_NANOSECONDS_PER_SEC)
3141 {
3142 ns -= NX_PTP_NANOSECONDS_PER_SEC;
3143 _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
3144 }
3145
3146 /* ensure the nanoseconds field has same sign as seconds field */
3147 if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0)))
3148 {
3149 /* positive number of seconds */
3150 if (ns < 0)
3151 {
3152 ns += NX_PTP_NANOSECONDS_PER_SEC;
3153 _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo);
3154 }
3155 }
3156 else if (sec_hi < 0)
3157 {
3158 /* negative number of seconds */
3159 if (ns > 0)
3160 {
3161 ns -= NX_PTP_NANOSECONDS_PER_SEC;
3162 _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo);
3163 }
3164 }
3165
3166 /* return result time */
3167 result_ptr -> second_high = sec_hi;
3168 result_ptr -> second_low = sec_lo;
3169 result_ptr -> nanosecond = ns;
3170
3171 return(NX_SUCCESS);
3172 }
3173
3174
3175 /**************************************************************************/
3176 /* */
3177 /* FUNCTION RELEASE */
3178 /* */
3179 /* _nxe_ptp_client_utility_convert_time_to_date PORTABLE C */
3180 /* 6.1.3 */
3181 /* AUTHOR */
3182 /* */
3183 /* Yuxin Zhou, Microsoft Corporation */
3184 /* */
3185 /* DESCRIPTION */
3186 /* */
3187 /* This function checks for errors on the PTP time conversion service. */
3188 /* */
3189 /* INPUT */
3190 /* */
3191 /* time_ptr Pointer to PTP time */
3192 /* offset signed second offset to add */
3193 /* the PTP time */
3194 /* date_time_ptr Pointer to resulting date */
3195 /* */
3196 /* OUTPUT */
3197 /* */
3198 /* status Completion status */
3199 /* */
3200 /* CALLS */
3201 /* */
3202 /* _nx_ptp_client_utility_convert_time_to_date */
3203 /* Actual time conversion service*/
3204 /* */
3205 /* CALLED BY */
3206 /* */
3207 /* Application */
3208 /* */
3209 /* RELEASE HISTORY */
3210 /* */
3211 /* DATE NAME DESCRIPTION */
3212 /* */
3213 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3214 /* */
3215 /**************************************************************************/
_nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME * time_ptr,LONG offset,NX_PTP_DATE_TIME * date_time_ptr)3216 UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
3217 {
3218
3219 /* Check input parameters. */
3220 if ((time_ptr == NX_NULL) || (date_time_ptr == NX_NULL))
3221 {
3222
3223 /* Return error status. */
3224 return(NX_PTR_ERROR);
3225 }
3226
3227 /* Check for appropriate caller. */
3228 NX_THREADS_ONLY_CALLER_CHECKING
3229
3230 /* Call the actual function. */
3231 return(_nx_ptp_client_utility_convert_time_to_date(time_ptr, offset, date_time_ptr));
3232 }
3233
3234
3235 /**************************************************************************/
3236 /* */
3237 /* FUNCTION RELEASE */
3238 /* */
3239 /* _nx_ptp_client_utility_convert_time_to_date PORTABLE C */
3240 /* 6.1.3 */
3241 /* AUTHOR */
3242 /* */
3243 /* Yuxin Zhou, Microsoft Corporation */
3244 /* */
3245 /* DESCRIPTION */
3246 /* */
3247 /* This function converts a PTP time to a UTC date and time. */
3248 /* */
3249 /* INPUT */
3250 /* */
3251 /* time_ptr Pointer to PTP time */
3252 /* offset Signed second offset to add */
3253 /* the PTP time */
3254 /* date_time_ptr Pointer to resulting date */
3255 /* */
3256 /* OUTPUT */
3257 /* */
3258 /* status Completion status */
3259 /* */
3260 /* CALLS */
3261 /* */
3262 /* _nx_ptp_client_utility_add64 Add two 64-bit number */
3263 /* */
3264 /* CALLED BY */
3265 /* */
3266 /* Application */
3267 /* */
3268 /* RELEASE HISTORY */
3269 /* */
3270 /* DATE NAME DESCRIPTION */
3271 /* */
3272 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3273 /* */
3274 /**************************************************************************/
_nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME * time_ptr,LONG offset,NX_PTP_DATE_TIME * date_time_ptr)3275 UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr)
3276 {
3277 #define IS_LEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
3278 #define SECS_PER_MINUTE 60
3279 #define SECS_PER_HOUR (60 * SECS_PER_MINUTE)
3280 #define SECS_PER_DAY (24 * SECS_PER_HOUR)
3281 LONG secs_high;
3282 ULONG secs_low;
3283 UINT year, month, day, hour, minute;
3284 ULONG secs_per_year, secs_per_month;
3285 ULONG weekday;
3286 UINT is_leap;
3287
3288 /* get number of seconds */
3289 secs_high = time_ptr -> second_high;
3290 secs_low = time_ptr -> second_low;
3291
3292 /* add local time offset */
3293 if (offset != 0)
3294 {
3295 _nx_ptp_client_utility_add64(&secs_high, &secs_low, offset < 0 ? -1 : 0, (ULONG)offset);
3296 }
3297 if (secs_high < 0)
3298 {
3299
3300 /* invalid negative time */
3301 return(NX_PTP_PARAM_ERROR);
3302 }
3303
3304 /* determine the current year from Epoch (January 1, 1970) */
3305 year = 1970;
3306 secs_per_year = 365 * SECS_PER_DAY;
3307 is_leap = 0;
3308 weekday = 4; /* thursday */
3309 while ((secs_high > 0) || (secs_low >= secs_per_year))
3310 {
3311 if (secs_low < secs_per_year)
3312 {
3313 secs_high--;
3314 }
3315 secs_low -= secs_per_year;
3316 weekday += is_leap ? 366 : 365;
3317 year++;
3318 is_leap = IS_LEAP(year) ? 1 : 0;
3319 secs_per_year = is_leap ? 366 * SECS_PER_DAY : 365 * SECS_PER_DAY;
3320 }
3321 /* compute day of the week from remaining seconds */
3322 weekday = (weekday + secs_low / SECS_PER_DAY) % 7;
3323
3324 /* determine current month */
3325 month = 1;
3326 secs_per_month = 31 * SECS_PER_DAY;
3327 while (secs_low >= secs_per_month)
3328 {
3329 secs_low -= secs_per_month;
3330 month++;
3331 if (month == 2)
3332 {
3333
3334 /* february */
3335 secs_per_month = is_leap ? 29 * SECS_PER_DAY : 28 * SECS_PER_DAY;
3336 }
3337 else if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
3338 {
3339
3340 /* april, june, september, november */
3341 secs_per_month = 30 * SECS_PER_DAY;
3342 }
3343 else
3344 {
3345
3346 /* the other months */
3347 secs_per_month = 31 * SECS_PER_DAY;
3348 }
3349 }
3350
3351 /* determine current day of the month */
3352 day = secs_low / SECS_PER_DAY;
3353 secs_low -= day * SECS_PER_DAY;
3354
3355 /* determine current hour */
3356 hour = secs_low / SECS_PER_HOUR;
3357 secs_low -= hour * SECS_PER_HOUR;
3358
3359 /* determine current minute */
3360 minute = secs_low / SECS_PER_MINUTE;
3361 secs_low -= minute * SECS_PER_MINUTE;
3362
3363 /* return date */
3364 date_time_ptr -> year = year;
3365 date_time_ptr -> month = (UCHAR)month;
3366 date_time_ptr -> day = (UCHAR)(day + 1);
3367 date_time_ptr -> hour = (UCHAR)hour;
3368 date_time_ptr -> minute = (UCHAR)minute;
3369 date_time_ptr -> second = (UCHAR)secs_low;
3370 date_time_ptr -> weekday = (UCHAR)weekday;
3371 date_time_ptr -> nanosecond = (ULONG)time_ptr -> nanosecond;
3372
3373 return(NX_SUCCESS);
3374 }
3375
3376
3377 /**************************************************************************/
3378 /* */
3379 /* FUNCTION RELEASE */
3380 /* */
3381 /* _nx_ptp_client_utility_add64 PORTABLE C */
3382 /* 6.1.3 */
3383 /* AUTHOR */
3384 /* */
3385 /* Yuxin Zhou, Microsoft Corporation */
3386 /* */
3387 /* DESCRIPTION */
3388 /* */
3389 /* This function adds two 64-bit numbers: A = A + B. */
3390 /* */
3391 /* INPUT */
3392 /* */
3393 /* a_hi Pointer to higher 32-bit of A */
3394 /* a_lo Pointer to lower 32-bit of A */
3395 /* b_hi higher 32-bit of B */
3396 /* b_lo lower 32-bit of B */
3397 /* */
3398 /* OUTPUT */
3399 /* */
3400 /* None */
3401 /* */
3402 /* CALLS */
3403 /* */
3404 /* None */
3405 /* */
3406 /* CALLED BY */
3407 /* */
3408 /* _nx_ptp_client_clock_adjust Adjust PTP clock */
3409 /* _nx_ptp_client_utility_convert_time_to_date */
3410 /* Convert time to date */
3411 /* */
3412 /* RELEASE HISTORY */
3413 /* */
3414 /* DATE NAME DESCRIPTION */
3415 /* */
3416 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3417 /* */
3418 /**************************************************************************/
_nx_ptp_client_utility_add64(LONG * a_hi,ULONG * a_lo,LONG b_hi,ULONG b_lo)3419 VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
3420 {
3421 LONG r_hi;
3422 ULONG r_lo;
3423
3424 r_hi = *a_hi + b_hi;
3425 r_lo = *a_lo + b_lo;
3426 if (r_lo < *a_lo)
3427 {
3428 r_hi++; /* add carry */
3429 }
3430 *a_hi = r_hi;
3431 *a_lo = r_lo;
3432 }
3433
3434
3435 /**************************************************************************/
3436 /* */
3437 /* FUNCTION RELEASE */
3438 /* */
3439 /* _nx_ptp_client_utility_sub64 PORTABLE C */
3440 /* 6.1.3 */
3441 /* AUTHOR */
3442 /* */
3443 /* Yuxin Zhou, Microsoft Corporation */
3444 /* */
3445 /* DESCRIPTION */
3446 /* */
3447 /* This function substracts two 64-bit numbers: A = A - B. */
3448 /* */
3449 /* INPUT */
3450 /* */
3451 /* a_hi Pointer to higher 32-bit of A */
3452 /* a_lo Pointer to lower 32-bit of A */
3453 /* b_hi higher 32-bit of B */
3454 /* b_lo lower 32-bit of B */
3455 /* */
3456 /* OUTPUT */
3457 /* */
3458 /* None */
3459 /* */
3460 /* CALLS */
3461 /* */
3462 /* None */
3463 /* */
3464 /* CALLED BY */
3465 /* */
3466 /* _nx_ptp_client_utility_time_diff Diff two PTP times */
3467 /* */
3468 /* RELEASE HISTORY */
3469 /* */
3470 /* DATE NAME DESCRIPTION */
3471 /* */
3472 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3473 /* */
3474 /**************************************************************************/
_nx_ptp_client_utility_sub64(LONG * a_hi,ULONG * a_lo,LONG b_hi,ULONG b_lo)3475 VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo)
3476 {
3477 LONG r_hi;
3478 ULONG r_lo;
3479
3480 r_hi = *a_hi - b_hi;
3481 r_lo = *a_lo - b_lo;
3482 if (*a_lo < b_lo)
3483 {
3484 r_hi--; /* substract carry */
3485 }
3486 *a_hi = r_hi;
3487 *a_lo = r_lo;
3488 }
3489
3490
3491 /**************************************************************************/
3492 /* */
3493 /* FUNCTION RELEASE */
3494 /* */
3495 /* _nx_ptp_client_utility_inc64 PORTABLE C */
3496 /* 6.1.3 */
3497 /* AUTHOR */
3498 /* */
3499 /* Yuxin Zhou, Microsoft Corporation */
3500 /* */
3501 /* DESCRIPTION */
3502 /* */
3503 /* This function increments a 64-bit number: A = A + 1. */
3504 /* */
3505 /* INPUT */
3506 /* */
3507 /* a_hi Pointer to higher 32-bit of A */
3508 /* a_lo Pointer to lower 32-bit of A */
3509 /* */
3510 /* OUTPUT */
3511 /* */
3512 /* None */
3513 /* */
3514 /* CALLS */
3515 /* */
3516 /* None */
3517 /* */
3518 /* CALLED BY */
3519 /* */
3520 /* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
3521 /* _nx_ptp_client_clock_adjust Adjust PTP clock */
3522 /* _nx_ptp_client_utility_time_diff Diff two PTP times */
3523 /* _nx_ptp_client_soft_clock_callback Soft PTP clock */
3524 /* */
3525 /* RELEASE HISTORY */
3526 /* */
3527 /* DATE NAME DESCRIPTION */
3528 /* */
3529 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3530 /* */
3531 /**************************************************************************/
_nx_ptp_client_utility_inc64(LONG * a_hi,ULONG * a_lo)3532 VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo)
3533 {
3534 ULONG r_lo;
3535
3536 r_lo = *a_lo + 1;
3537 if (r_lo == 0)
3538 {
3539 *a_hi = *a_hi + 1; /* add carry */
3540 }
3541 *a_lo = r_lo;
3542 }
3543
3544
3545 /**************************************************************************/
3546 /* */
3547 /* FUNCTION RELEASE */
3548 /* */
3549 /* _nx_ptp_client_utility_dec64 PORTABLE C */
3550 /* 6.1.3 */
3551 /* AUTHOR */
3552 /* */
3553 /* Yuxin Zhou, Microsoft Corporation */
3554 /* */
3555 /* DESCRIPTION */
3556 /* */
3557 /* This function decrements a 64-bit number: A = A - 1. */
3558 /* */
3559 /* INPUT */
3560 /* */
3561 /* a_hi Pointer to higher 32-bit of A */
3562 /* a_lo Pointer to lower 32-bit of A */
3563 /* */
3564 /* OUTPUT */
3565 /* */
3566 /* None */
3567 /* */
3568 /* CALLS */
3569 /* */
3570 /* None */
3571 /* */
3572 /* CALLED BY */
3573 /* */
3574 /* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */
3575 /* _nx_ptp_client_clock_adjust Adjust PTP clock */
3576 /* _nx_ptp_client_utility_time_diff Diff two PTP times */
3577 /* */
3578 /* RELEASE HISTORY */
3579 /* */
3580 /* DATE NAME DESCRIPTION */
3581 /* */
3582 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3583 /* */
3584 /**************************************************************************/
_nx_ptp_client_utility_dec64(LONG * a_hi,ULONG * a_lo)3585 VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo)
3586 {
3587 ULONG r_lo;
3588
3589 r_lo = *a_lo;
3590 if (r_lo == 0)
3591 {
3592 *a_hi = *a_hi - 1; /* substract carry */
3593 }
3594 *a_lo = r_lo - 1;
3595 }
3596
3597
3598 /**************************************************************************/
3599 /* */
3600 /* FUNCTION RELEASE */
3601 /* */
3602 /* _nx_ptp_client_utility_neg64 PORTABLE C */
3603 /* 6.1.3 */
3604 /* AUTHOR */
3605 /* */
3606 /* Yuxin Zhou, Microsoft Corporation */
3607 /* */
3608 /* DESCRIPTION */
3609 /* */
3610 /* This function changes the sign of a 64-bit number: A = -A. */
3611 /* */
3612 /* INPUT */
3613 /* */
3614 /* a_hi Pointer to higher 32-bit of A */
3615 /* a_lo Pointer to lower 32-bit of A */
3616 /* */
3617 /* OUTPUT */
3618 /* */
3619 /* None */
3620 /* */
3621 /* CALLS */
3622 /* */
3623 /* None */
3624 /* */
3625 /* CALLED BY */
3626 /* */
3627 /* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */
3628 /* */
3629 /* RELEASE HISTORY */
3630 /* */
3631 /* DATE NAME DESCRIPTION */
3632 /* */
3633 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3634 /* */
3635 /**************************************************************************/
_nx_ptp_client_utility_neg64(LONG * a_hi,ULONG * a_lo)3636 VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo)
3637 {
3638 LONG r_hi;
3639
3640 r_hi = -*a_hi;
3641 if (*a_lo != 0)
3642 {
3643 r_hi--; /* substract carry */
3644 }
3645 *a_hi = r_hi;
3646 *a_lo = -*a_lo;
3647 }
3648
3649
3650 /**************************************************************************/
3651 /* */
3652 /* FUNCTION RELEASE */
3653 /* */
3654 /* _nx_ptp_client_utility_time_div_by_2 PORTABLE C */
3655 /* 6.1.3 */
3656 /* AUTHOR */
3657 /* */
3658 /* Yuxin Zhou, Microsoft Corporation */
3659 /* */
3660 /* DESCRIPTION */
3661 /* */
3662 /* This function divides a PTP time by 2. */
3663 /* */
3664 /* INPUT */
3665 /* */
3666 /* time_ptr Pointer to PTP time */
3667 /* */
3668 /* OUTPUT */
3669 /* */
3670 /* None */
3671 /* */
3672 /* CALLS */
3673 /* */
3674 /* _nx_ptp_client_utility_neg64 Change the sign of number */
3675 /* */
3676 /* CALLED BY */
3677 /* */
3678 /* _nx_ptp_client_delay_resp_received Process delay response */
3679 /* */
3680 /* RELEASE HISTORY */
3681 /* */
3682 /* DATE NAME DESCRIPTION */
3683 /* */
3684 /* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */
3685 /* */
3686 /**************************************************************************/
_nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME * time_ptr)3687 VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr)
3688 {
3689 UINT neg;
3690 LONG sec_hi;
3691 ULONG sec_lo;
3692 LONG ns;
3693
3694 /* get current time value */
3695 sec_hi = time_ptr -> second_high;
3696 sec_lo = time_ptr -> second_low;
3697 ns = time_ptr -> nanosecond;
3698
3699 /* implement division on unsigned values */
3700 if ((sec_hi < 0) || (ns < 0))
3701 {
3702 _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
3703 ns = -ns;
3704 neg = 1;
3705 }
3706 else
3707 {
3708 neg = 0;
3709 }
3710
3711 /* divide nanoseconds by two */
3712 ns >>= 1;
3713 if (sec_lo & 1)
3714 {
3715
3716 /* add rest of seconds division */
3717 ns += 500000000L;
3718 }
3719
3720 /* divide seconds by two */
3721 sec_lo >>= 1;
3722 if (sec_hi & 1)
3723 {
3724 sec_lo |= 0x80000000UL;
3725 }
3726 sec_hi >>= 1;
3727
3728 /* restore sign */
3729 if (neg)
3730 {
3731 _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo);
3732 ns = -ns;
3733 }
3734
3735 /* return result */
3736 time_ptr -> second_high = sec_hi;
3737 time_ptr -> second_low = sec_lo;
3738 time_ptr -> nanosecond = ns;
3739 }
3740