mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	module-rtp-sap: support PTP management protocol
Request current clock sync status to know the grandmaster identity for SAP announcements
This commit is contained in:
		
							parent
							
								
									2f46ee2793
								
							
						
					
					
						commit
						7abb896aef
					
				
					 3 changed files with 239 additions and 7 deletions
				
			
		| 
						 | 
					@ -68,6 +68,7 @@ context.modules = [
 | 
				
			||||||
            sap.port = 9875
 | 
					            sap.port = 9875
 | 
				
			||||||
            net.ttl = 32
 | 
					            net.ttl = 32
 | 
				
			||||||
            net.loop = false
 | 
					            net.loop = false
 | 
				
			||||||
 | 
					            ptp.management-socket = "/var/run/ptp4lro"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            stream.rules = [
 | 
					            stream.rules = [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
| 
						 | 
					@ -116,7 +117,6 @@ context.modules = [
 | 
				
			||||||
            # please change this, especially for multiple streams
 | 
					            # please change this, especially for multiple streams
 | 
				
			||||||
            sess.name = "PipeWire RTP stream"
 | 
					            sess.name = "PipeWire RTP stream"
 | 
				
			||||||
            sess.media = "audio"
 | 
					            sess.media = "audio"
 | 
				
			||||||
            ### please select the PTP grandmaster ID here
 | 
					 | 
				
			||||||
            sess.ts-refclk = "ptp=traceable"
 | 
					            sess.ts-refclk = "ptp=traceable"
 | 
				
			||||||
            sess.ts-offset = 0
 | 
					            sess.ts-offset = 0
 | 
				
			||||||
            sess.latency.msec = 3
 | 
					            sess.latency.msec = 3
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,7 @@ context.modules = [
 | 
				
			||||||
                node.always-process = true
 | 
					                node.always-process = true
 | 
				
			||||||
                node.group = pipewire.ptp0
 | 
					                node.group = pipewire.ptp0
 | 
				
			||||||
                rtp.ntp = 0
 | 
					                rtp.ntp = 0
 | 
				
			||||||
 | 
					                rtp.fetch-ts-refclk = true
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
/* SPDX-License-Identifier: MIT */
 | 
					/* SPDX-License-Identifier: MIT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
 | 
					#include "pipewire/properties.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
| 
						 | 
					@ -24,6 +25,7 @@
 | 
				
			||||||
#include <pipewire/impl.h>
 | 
					#include <pipewire/impl.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <module-rtp/sap.h>
 | 
					#include <module-rtp/sap.h>
 | 
				
			||||||
 | 
					#include <module-rtp/ptp.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __FreeBSD__
 | 
					#ifdef __FreeBSD__
 | 
				
			||||||
#define ifr_ifindex ifr_index
 | 
					#define ifr_ifindex ifr_index
 | 
				
			||||||
| 
						 | 
					@ -164,6 +166,13 @@ static const struct spa_dict_item module_info[] = {
 | 
				
			||||||
	{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
 | 
						{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PTP_MESSAGE_TYPE_MANAGEMENT 0x0d
 | 
				
			||||||
 | 
					#define PTP_VERSION_1588_2008_2_1 0x12
 | 
				
			||||||
 | 
					#define PTP_DEFAULT_LOG_MESSAGE_INTERVAL 127
 | 
				
			||||||
 | 
					#define PTP_MGMT_ACTION_GET 0
 | 
				
			||||||
 | 
					#define PTP_TLV_TYPE_MGMT 0x0001
 | 
				
			||||||
 | 
					#define PTP_MGMT_ID_PARENT_DATA_SET 0x2002
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sdp_info {
 | 
					struct sdp_info {
 | 
				
			||||||
	uint16_t hash;
 | 
						uint16_t hash;
 | 
				
			||||||
	uint32_t ntp;
 | 
						uint32_t ntp;
 | 
				
			||||||
| 
						 | 
					@ -198,6 +207,7 @@ struct session {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool announce;
 | 
						bool announce;
 | 
				
			||||||
	uint64_t timestamp;
 | 
						uint64_t timestamp;
 | 
				
			||||||
 | 
						bool ts_refclk_ptp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	struct node *node;
 | 
						struct node *node;
 | 
				
			||||||
| 
						 | 
					@ -262,6 +272,13 @@ struct impl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *extra_attrs_preamble;
 | 
						char *extra_attrs_preamble;
 | 
				
			||||||
	char *extra_attrs_end;
 | 
						char *extra_attrs_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						char *ptp_mgmt_socket;
 | 
				
			||||||
 | 
						char ptp_client_path[64];
 | 
				
			||||||
 | 
						int ptp_fd;
 | 
				
			||||||
 | 
						uint32_t ptp_seq;
 | 
				
			||||||
 | 
						uint8_t clock_id[8];
 | 
				
			||||||
 | 
						uint8_t gm_id[8];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct format_info {
 | 
					struct format_info {
 | 
				
			||||||
| 
						 | 
					@ -367,6 +384,37 @@ static bool is_multicast(struct sockaddr *sa, socklen_t salen)
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int make_unix_socket(char *path, char *client_path) {
 | 
				
			||||||
 | 
						struct sockaddr_un client_addr, server_addr;
 | 
				
			||||||
 | 
						int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fd = socket(AF_UNIX, SOCK_DGRAM, 0);
 | 
				
			||||||
 | 
						if (fd == -1) {
 | 
				
			||||||
 | 
							pw_log_warn("Failed to create PTP management socket");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_zero(client_addr);
 | 
				
			||||||
 | 
						client_addr.sun_family = AF_UNIX;
 | 
				
			||||||
 | 
						strncpy(client_addr.sun_path, client_path, strlen(client_path));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (bind(fd, (struct sockaddr *)&client_addr, sizeof(client_addr)) == -1) {
 | 
				
			||||||
 | 
							pw_log_warn("Failed to bind PTP management socket");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_zero(server_addr);
 | 
				
			||||||
 | 
						server_addr.sun_family = AF_UNIX;
 | 
				
			||||||
 | 
						strncpy(server_addr.sun_path, path, sizeof(server_addr.sun_path) - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (connect(fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
 | 
				
			||||||
 | 
							pw_log_warn("Failed to connect PTP management socket");
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int make_send_socket(
 | 
					static int make_send_socket(
 | 
				
			||||||
		struct sockaddr_storage *src, socklen_t src_len,
 | 
							struct sockaddr_storage *src, socklen_t src_len,
 | 
				
			||||||
		struct sockaddr_storage *sa, socklen_t salen,
 | 
							struct sockaddr_storage *sa, socklen_t salen,
 | 
				
			||||||
| 
						 | 
					@ -490,6 +538,96 @@ static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_ts_refclk(struct impl *impl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!impl->ptp_mgmt_socket || !impl->ptp_fd)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read if something is left in the socket
 | 
				
			||||||
 | 
						int avail;
 | 
				
			||||||
 | 
						ioctl(impl->ptp_fd, FIONREAD, &avail);
 | 
				
			||||||
 | 
						if (avail) {
 | 
				
			||||||
 | 
							void *tmp = malloc(avail);
 | 
				
			||||||
 | 
							read(impl->ptp_fd, tmp, avail);
 | 
				
			||||||
 | 
							free(tmp);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ptp_management_msg req;
 | 
				
			||||||
 | 
						spa_zero(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req.major_sdo_id_message_type = PTP_MESSAGE_TYPE_MANAGEMENT;
 | 
				
			||||||
 | 
						req.ver = PTP_VERSION_1588_2008_2_1;
 | 
				
			||||||
 | 
						req.message_length_be = htobe16(sizeof(struct ptp_management_msg));
 | 
				
			||||||
 | 
						spa_zero(req.clock_identity);
 | 
				
			||||||
 | 
						req.source_port_id_be = htobe16(getpid());
 | 
				
			||||||
 | 
						req.log_message_interval = 127;
 | 
				
			||||||
 | 
						req.sequence_id_be = htobe16(impl->ptp_seq++);
 | 
				
			||||||
 | 
						memset(req.target_port_identity, 0xff, 8);
 | 
				
			||||||
 | 
						req.target_port_id_be = htobe16(0xffff);
 | 
				
			||||||
 | 
						req.starting_boundary_hops = 1;
 | 
				
			||||||
 | 
						req.boundary_hops = 1;
 | 
				
			||||||
 | 
						req.action = PTP_MGMT_ACTION_GET;
 | 
				
			||||||
 | 
						req.tlv_type_be = htobe16(PTP_TLV_TYPE_MGMT);
 | 
				
			||||||
 | 
						// sent empty TLV, only sending management_id
 | 
				
			||||||
 | 
						req.management_message_length_be = htobe16(2);
 | 
				
			||||||
 | 
						req.management_id_be = htobe16(PTP_MGMT_ID_PARENT_DATA_SET);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (write(impl->ptp_fd, &req, sizeof(req)) == -1) {
 | 
				
			||||||
 | 
							pw_log_warn("Failed to send PTP management request: %m");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint8_t buf[sizeof(struct ptp_management_msg) + sizeof(struct ptp_parent_data_set)];
 | 
				
			||||||
 | 
						if (read(impl->ptp_fd, &buf, sizeof(buf)) == -1) {
 | 
				
			||||||
 | 
							pw_log_warn("Failed to send PTP management request: %m");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct ptp_management_msg res = *(struct ptp_management_msg *)buf;
 | 
				
			||||||
 | 
						struct ptp_parent_data_set parent =
 | 
				
			||||||
 | 
							*(struct ptp_parent_data_set *)(buf + sizeof(struct ptp_management_msg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint16_t data_len = be16toh(res.management_message_length_be) - 2;
 | 
				
			||||||
 | 
						if (data_len != sizeof(struct ptp_parent_data_set))
 | 
				
			||||||
 | 
							pw_log_warn("Unexpected PTP GET PARENT_DATA_SET response length %u, expected 32", data_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint8_t *cid = res.clock_identity;
 | 
				
			||||||
 | 
						if (memcmp(cid, impl->clock_id, 8) != 0)
 | 
				
			||||||
 | 
							pw_log_info(
 | 
				
			||||||
 | 
								"Local clock ID: IEEE1588-2008:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X:%d",
 | 
				
			||||||
 | 
								cid[0],
 | 
				
			||||||
 | 
								cid[1],
 | 
				
			||||||
 | 
								cid[2],
 | 
				
			||||||
 | 
								cid[3],
 | 
				
			||||||
 | 
								cid[4],
 | 
				
			||||||
 | 
								cid[5],
 | 
				
			||||||
 | 
								cid[6],
 | 
				
			||||||
 | 
								cid[7],
 | 
				
			||||||
 | 
								0 /* domain */
 | 
				
			||||||
 | 
						  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint8_t *gmid = parent.gm_clock_id;
 | 
				
			||||||
 | 
						if (memcmp(gmid, impl->gm_id, 8) != 0)
 | 
				
			||||||
 | 
							pw_log_info(
 | 
				
			||||||
 | 
								"GM ID: IEEE1588-2008:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X:%d",
 | 
				
			||||||
 | 
								gmid[0],
 | 
				
			||||||
 | 
								gmid[1],
 | 
				
			||||||
 | 
								gmid[2],
 | 
				
			||||||
 | 
								gmid[3],
 | 
				
			||||||
 | 
								gmid[4],
 | 
				
			||||||
 | 
								gmid[5],
 | 
				
			||||||
 | 
								gmid[6],
 | 
				
			||||||
 | 
								gmid[7],
 | 
				
			||||||
 | 
								0 /* domain */
 | 
				
			||||||
 | 
						  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// When GM is not equal to own clock we are clocked by external master
 | 
				
			||||||
 | 
						pw_log_debug("Synced to GM: %s", (memcmp(cid, gmid, 8) != 0) ? "true" : "false");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memcpy(impl->clock_id, cid, 8);
 | 
				
			||||||
 | 
						memcpy(impl->gm_id, gmid, 8);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int send_sap(struct impl *impl, struct session *sess, bool bye)
 | 
					static int send_sap(struct impl *impl, struct session *sess, bool bye)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char buffer[2048], src_addr[64], dst_addr[64], dst_ttl[8];
 | 
						char buffer[2048], src_addr[64], dst_addr[64], dst_ttl[8];
 | 
				
			||||||
| 
						 | 
					@ -596,12 +734,24 @@ static int send_sap(struct impl *impl, struct session *sess, bool bye)
 | 
				
			||||||
		spa_strbuf_append(&buf,
 | 
							spa_strbuf_append(&buf,
 | 
				
			||||||
			"a=framecount:%u\n", sdp->framecount);
 | 
								"a=framecount:%u\n", sdp->framecount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdp->ts_refclk != NULL) {
 | 
						if (sdp->ts_refclk != NULL || sess->ts_refclk_ptp) {
 | 
				
			||||||
 | 
							// Only broadcast the GM ID when we are synced to external time source
 | 
				
			||||||
 | 
							if (sess->ts_refclk_ptp && memcmp(impl->clock_id, impl->gm_id, 8) != 0) {
 | 
				
			||||||
			spa_strbuf_append(&buf,
 | 
								spa_strbuf_append(&buf,
 | 
				
			||||||
				"a=ts-refclk:%s\n"
 | 
										"a=ts-refclk:ptp=IEEE1588-2008:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X:%d\n",
 | 
				
			||||||
				"a=mediaclk:direct=%u\n",
 | 
										impl->gm_id[0],
 | 
				
			||||||
				sdp->ts_refclk,
 | 
										impl->gm_id[1],
 | 
				
			||||||
				sdp->ts_offset);
 | 
										impl->gm_id[2],
 | 
				
			||||||
 | 
										impl->gm_id[3],
 | 
				
			||||||
 | 
										impl->gm_id[4],
 | 
				
			||||||
 | 
										impl->gm_id[5],
 | 
				
			||||||
 | 
										impl->gm_id[6],
 | 
				
			||||||
 | 
										impl->gm_id[7],
 | 
				
			||||||
 | 
										0/* domain */);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								spa_strbuf_append(&buf,	"a=ts-refclk:%s\n",	sdp->ts_refclk);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							spa_strbuf_append(&buf,	"a=mediaclk:direct=%u\n",	sdp->ts_offset);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		spa_strbuf_append(&buf, "a=mediaclk:sender\n");
 | 
							spa_strbuf_append(&buf, "a=mediaclk:sender\n");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -646,6 +796,7 @@ static void on_timer_event(void *data, uint64_t expirations)
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &ts);
 | 
						clock_gettime(CLOCK_MONOTONIC, &ts);
 | 
				
			||||||
	timestamp = SPA_TIMESPEC_TO_NSEC(&ts);
 | 
						timestamp = SPA_TIMESPEC_TO_NSEC(&ts);
 | 
				
			||||||
	interval = impl->cleanup_interval * SPA_NSEC_PER_SEC;
 | 
						interval = impl->cleanup_interval * SPA_NSEC_PER_SEC;
 | 
				
			||||||
 | 
						update_ts_refclk(impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each_safe(sess, tmp, &impl->sessions, link) {
 | 
						spa_list_for_each_safe(sess, tmp, &impl->sessions, link) {
 | 
				
			||||||
		if (sess->announce) {
 | 
							if (sess->announce) {
 | 
				
			||||||
| 
						 | 
					@ -739,6 +890,7 @@ static struct session *session_new_announce(struct impl *impl, struct node *node
 | 
				
			||||||
		sdp->ts_offset = atoi(str);
 | 
							sdp->ts_offset = atoi(str);
 | 
				
			||||||
	if ((str = pw_properties_get(props, "rtp.ts-refclk")) != NULL)
 | 
						if ((str = pw_properties_get(props, "rtp.ts-refclk")) != NULL)
 | 
				
			||||||
		sdp->ts_refclk = strdup(str);
 | 
							sdp->ts_refclk = strdup(str);
 | 
				
			||||||
 | 
						sess->ts_refclk_ptp = pw_properties_get_bool(props, "rtp.fetch-ts-refclk", false);
 | 
				
			||||||
	if ((str = pw_properties_get(props, PW_KEY_NODE_CHANNELNAMES)) != NULL) {
 | 
						if ((str = pw_properties_get(props, PW_KEY_NODE_CHANNELNAMES)) != NULL) {
 | 
				
			||||||
		struct spa_strbuf buf;
 | 
							struct spa_strbuf buf;
 | 
				
			||||||
		spa_strbuf_init(&buf, sdp->channelmap, sizeof(sdp->channelmap));
 | 
							spa_strbuf_init(&buf, sdp->channelmap, sizeof(sdp->channelmap));
 | 
				
			||||||
| 
						 | 
					@ -1464,12 +1616,16 @@ static void impl_destroy(struct impl *impl)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->sap_fd != -1)
 | 
						if (impl->sap_fd != -1)
 | 
				
			||||||
		close(impl->sap_fd);
 | 
							close(impl->sap_fd);
 | 
				
			||||||
 | 
						if (impl->ptp_fd != -1)
 | 
				
			||||||
 | 
							close(impl->ptp_fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_properties_free(impl->props);
 | 
						pw_properties_free(impl->props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(impl->extra_attrs_preamble);
 | 
						free(impl->extra_attrs_preamble);
 | 
				
			||||||
	free(impl->extra_attrs_end);
 | 
						free(impl->extra_attrs_end);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						free(impl->ptp_mgmt_socket);
 | 
				
			||||||
 | 
						unlink(impl->ptp_client_path);
 | 
				
			||||||
	free(impl->ifname);
 | 
						free(impl->ifname);
 | 
				
			||||||
	free(impl);
 | 
						free(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1539,6 +1695,20 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
 | 
				
			||||||
	str = pw_properties_get(props, "local.ifname");
 | 
						str = pw_properties_get(props, "local.ifname");
 | 
				
			||||||
	impl->ifname = str ? strdup(str) : NULL;
 | 
						impl->ifname = str ? strdup(str) : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str = pw_properties_get(props, "ptp.management-socket");
 | 
				
			||||||
 | 
						impl->ptp_mgmt_socket = str ? strdup(str) : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (impl->ptp_mgmt_socket) {
 | 
				
			||||||
 | 
							char *client_dir = getenv("PIPEWIRE_RUNTIME_DIR");
 | 
				
			||||||
 | 
							if (!client_dir) client_dir = getenv("XDG_RUNTIME_DIR");
 | 
				
			||||||
 | 
							if (!client_dir) client_dir = "/tmp";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							snprintf(impl->ptp_client_path, 63, "%s/pipewire-ptp-mgmt.%d", client_dir, getpid());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TODO: support UDP management access as well
 | 
				
			||||||
 | 
							impl->ptp_fd = make_unix_socket(impl->ptp_mgmt_socket, impl->ptp_client_path);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = pw_properties_get(props, "sap.ip")) == NULL)
 | 
						if ((str = pw_properties_get(props, "sap.ip")) == NULL)
 | 
				
			||||||
		str = DEFAULT_SAP_IP;
 | 
							str = DEFAULT_SAP_IP;
 | 
				
			||||||
	port = pw_properties_get_uint32(props, "sap.port", DEFAULT_SAP_PORT);
 | 
						port = pw_properties_get_uint32(props, "sap.port", DEFAULT_SAP_PORT);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/modules/module-rtp/ptp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/modules/module-rtp/ptp.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					/* PipeWire */
 | 
				
			||||||
 | 
					/* SPDX-FileCopyrightText: Copyright © 2024 Dmitry Sharshakov <d3dx12.xx@gmail.com> */
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: MIT */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef PIPEWIRE_PTP_H
 | 
				
			||||||
 | 
					#define PIPEWIRE_PTP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ptp_management_msg {
 | 
				
			||||||
 | 
							// 4 for major_sdo, 4 for msg_type
 | 
				
			||||||
 | 
							uint8_t  major_sdo_id_message_type;
 | 
				
			||||||
 | 
							// 4 for minor, 4 for major
 | 
				
			||||||
 | 
							uint8_t  ver;
 | 
				
			||||||
 | 
							uint16_t message_length_be;
 | 
				
			||||||
 | 
							uint8_t  domain_number;
 | 
				
			||||||
 | 
							uint8_t  minor_sdo_id;
 | 
				
			||||||
 | 
							uint16_t flags_be;
 | 
				
			||||||
 | 
							uint8_t  correction_field[8];
 | 
				
			||||||
 | 
							uint32_t message_type_specific;
 | 
				
			||||||
 | 
							uint8_t  clock_identity[8];
 | 
				
			||||||
 | 
							uint16_t source_port_id_be;
 | 
				
			||||||
 | 
							uint16_t sequence_id_be;
 | 
				
			||||||
 | 
							uint8_t  control_field;
 | 
				
			||||||
 | 
							uint8_t  log_message_interval;
 | 
				
			||||||
 | 
							uint8_t  target_port_identity[8];
 | 
				
			||||||
 | 
							uint16_t target_port_id_be;
 | 
				
			||||||
 | 
							uint8_t  starting_boundary_hops;
 | 
				
			||||||
 | 
							uint8_t  boundary_hops;
 | 
				
			||||||
 | 
							uint8_t  action;
 | 
				
			||||||
 | 
							uint8_t  reserved;
 | 
				
			||||||
 | 
							uint16_t tlv_type_be;
 | 
				
			||||||
 | 
							// length of data after this + 2 for management_id
 | 
				
			||||||
 | 
							uint16_t management_message_length_be;
 | 
				
			||||||
 | 
							uint16_t management_id_be;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ptp_parent_data_set {
 | 
				
			||||||
 | 
							uint8_t  parent_clock_id[8];
 | 
				
			||||||
 | 
							uint16_t parent_port_id_be;
 | 
				
			||||||
 | 
							uint8_t  parent_stats;
 | 
				
			||||||
 | 
							uint8_t  reserved;
 | 
				
			||||||
 | 
							uint16_t log_variance_be;
 | 
				
			||||||
 | 
							int32_t  phase_change_rate_be;
 | 
				
			||||||
 | 
							uint8_t  gm_prio1;
 | 
				
			||||||
 | 
							uint8_t  gm_clock_class;
 | 
				
			||||||
 | 
							uint8_t  gm_clock_accuracy;
 | 
				
			||||||
 | 
							uint16_t gm_clock_variance_be;
 | 
				
			||||||
 | 
							uint8_t  gm_prio2;
 | 
				
			||||||
 | 
							uint8_t  gm_clock_id[8];
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* PIPEWIRE_PTP_H */
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue