mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
avb: don't include ethernet header in in packets
Move vlan_id and prio to the stream.
This commit is contained in:
parent
dec2bdf241
commit
9bfb23f3f8
16 changed files with 217 additions and 174 deletions
|
|
@ -65,20 +65,8 @@ stream.properties = {
|
|||
|
||||
avb.properties = {
|
||||
# the addresses this server listens on
|
||||
#ifname = "eth0.2"
|
||||
ifname = "enp3s0"
|
||||
server.address = [
|
||||
"unix:native"
|
||||
#"unix:/tmp/something" # absolute paths may be used
|
||||
#"tcp:4713" # IPv4 and IPv6 on all addresses
|
||||
#"tcp:[::]:9999" # IPv6 on all addresses
|
||||
#"tcp:127.0.0.1:8888" # IPv4 on a single address
|
||||
#
|
||||
#{ address = "tcp:4713" # address
|
||||
# max-clients = 64 # maximum number of clients
|
||||
# listen-backlog = 32 # backlog in the server listen queue
|
||||
# client.access = "restricted" # permissions for clients
|
||||
#}
|
||||
]
|
||||
# These overrides are only applied when running in a vm.
|
||||
vm.overrides = {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
#define AVB_AAF_H
|
||||
|
||||
struct avb_packet_aaf {
|
||||
struct avb_ethernet_header hdr;
|
||||
uint8_t subtype;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sv:1;
|
||||
|
|
|
|||
|
|
@ -57,21 +57,25 @@ struct acmp {
|
|||
};
|
||||
|
||||
static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms,
|
||||
const struct avb_packet_acmp *m, size_t size)
|
||||
const void *m, size_t size)
|
||||
{
|
||||
struct pending *p;
|
||||
struct avb_ethernet_header *h;
|
||||
struct avb_packet_acmp *pm;
|
||||
|
||||
p = calloc(1, sizeof(*p) + size);
|
||||
if (p == NULL)
|
||||
return NULL;
|
||||
p->last_time = now;
|
||||
p->timeout = timeout_ms * SPA_NSEC_PER_MSEC;
|
||||
p->old_sequence_id = ntohs(m->sequence_id);
|
||||
p->sequence_id = acmp->sequence_id[type]++;
|
||||
p->size = size;
|
||||
p->ptr = SPA_PTROFF(p, sizeof(*p), void);
|
||||
memcpy(p->ptr, m, size);
|
||||
pm = p->ptr;
|
||||
|
||||
h = p->ptr;
|
||||
pm = SPA_PTROFF(h, sizeof(*h), void);
|
||||
p->old_sequence_id = ntohs(pm->sequence_id);
|
||||
pm->sequence_id = htons(p->sequence_id);
|
||||
spa_list_append(&acmp->pending[type], &p->link);
|
||||
|
||||
|
|
@ -103,39 +107,39 @@ static int reply_not_supported(struct acmp *acmp, uint8_t type, const void *m, i
|
|||
{
|
||||
struct server *server = acmp->server;
|
||||
uint8_t buf[len];
|
||||
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
memcpy(reply, m, len);
|
||||
memcpy(h, m, len);
|
||||
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, type);
|
||||
AVB_PACKET_ACMP_SET_STATUS(reply, AVB_ACMP_STATUS_NOT_SUPPORTED);
|
||||
|
||||
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||
AVB_TSN_ETH, reply, len);
|
||||
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
|
||||
}
|
||||
|
||||
static int retry_pending(struct acmp *acmp, uint64_t now, struct pending *p)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
struct avb_packet_acmp *cmd = p->ptr;
|
||||
struct avb_ethernet_header *h = p->ptr;
|
||||
p->retry++;
|
||||
p->last_time = now;
|
||||
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||
AVB_TSN_ETH, cmd, p->size);
|
||||
return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, p->ptr, p->size);
|
||||
}
|
||||
|
||||
static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
uint8_t buf[len];
|
||||
const struct avb_packet_acmp *p = m;
|
||||
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
|
||||
int status = AVB_ACMP_STATUS_SUCCESS;
|
||||
struct stream *stream;
|
||||
|
||||
if (be64toh(p->talker_guid) != server->entity_id)
|
||||
return 0;
|
||||
|
||||
memcpy(reply, m, len);
|
||||
memcpy(buf, m, len);
|
||||
stream = server_find_stream(server, SPA_DIRECTION_OUTPUT,
|
||||
reply->talker_unique_id);
|
||||
if (stream == NULL) {
|
||||
|
|
@ -150,18 +154,18 @@ static int handle_connect_tx_command(struct acmp *acmp, uint64_t now, const void
|
|||
|
||||
memcpy(reply->stream_dest_mac, stream->addr, 6);
|
||||
reply->connection_count = htons(1);
|
||||
reply->stream_vlan_id = htons(2);
|
||||
reply->stream_vlan_id = htons(stream->vlan_id);
|
||||
|
||||
done:
|
||||
AVB_PACKET_ACMP_SET_STATUS(reply, status);
|
||||
return avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, len);
|
||||
return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len);
|
||||
}
|
||||
|
||||
static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
const struct avb_packet_acmp *resp = m;
|
||||
struct avb_ethernet_header *h;
|
||||
const struct avb_packet_acmp *resp = SPA_PTROFF(m, sizeof(*h), void);
|
||||
struct avb_packet_acmp *reply;
|
||||
struct pending *pending;
|
||||
uint16_t sequence_id;
|
||||
|
|
@ -177,13 +181,16 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
|
|||
if (pending == NULL)
|
||||
return 0;
|
||||
|
||||
reply = pending->ptr;
|
||||
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
||||
h = pending->ptr;
|
||||
pending->size = SPA_MIN((int)pending->size, len);
|
||||
memcpy(h, m, pending->size);
|
||||
|
||||
reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
reply->sequence_id = htons(pending->old_sequence_id);
|
||||
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE);
|
||||
|
||||
stream = server_find_stream(server, SPA_DIRECTION_INPUT,
|
||||
reply->listener_unique_id);
|
||||
ntohs(reply->listener_unique_id));
|
||||
if (stream == NULL)
|
||||
return 0;
|
||||
|
||||
|
|
@ -191,8 +198,7 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
|
|||
memcpy(stream->addr, reply->stream_dest_mac, 6);
|
||||
stream_activate(stream, now);
|
||||
|
||||
res = avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, pending->size);
|
||||
res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size);
|
||||
|
||||
pending_free(acmp, pending);
|
||||
|
||||
|
|
@ -203,15 +209,16 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v
|
|||
{
|
||||
struct server *server = acmp->server;
|
||||
uint8_t buf[len];
|
||||
const struct avb_packet_acmp *p = m;
|
||||
struct avb_packet_acmp *reply = (struct avb_packet_acmp*)buf;
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_acmp *reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
|
||||
int status = AVB_ACMP_STATUS_SUCCESS;
|
||||
struct stream *stream;
|
||||
|
||||
if (be64toh(p->talker_guid) != server->entity_id)
|
||||
return 0;
|
||||
|
||||
memcpy(reply, m, len);
|
||||
memcpy(buf, m, len);
|
||||
stream = server_find_stream(server, SPA_DIRECTION_OUTPUT,
|
||||
reply->talker_unique_id);
|
||||
if (stream == NULL) {
|
||||
|
|
@ -225,15 +232,15 @@ static int handle_disconnect_tx_command(struct acmp *acmp, uint64_t now, const v
|
|||
|
||||
done:
|
||||
AVB_PACKET_ACMP_SET_STATUS(reply, status);
|
||||
return avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, len);
|
||||
return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, buf, len);
|
||||
}
|
||||
|
||||
static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
const struct avb_packet_acmp *resp = m;
|
||||
struct avb_ethernet_header *h;
|
||||
struct avb_packet_acmp *reply;
|
||||
const struct avb_packet_acmp *resp = SPA_PTROFF(m, sizeof(*h), void);
|
||||
struct pending *pending;
|
||||
uint16_t sequence_id;
|
||||
struct stream *stream;
|
||||
|
|
@ -248,8 +255,11 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
|||
if (pending == NULL)
|
||||
return 0;
|
||||
|
||||
reply = pending->ptr;
|
||||
memcpy(reply, resp, SPA_MIN((int)pending->size, len));
|
||||
h = pending->ptr;
|
||||
pending->size = SPA_MIN((int)pending->size, len);
|
||||
memcpy(h, m, pending->size);
|
||||
|
||||
reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
reply->sequence_id = htons(pending->old_sequence_id);
|
||||
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
|
||||
|
||||
|
|
@ -260,8 +270,7 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
|||
|
||||
stream_deactivate(stream, now);
|
||||
|
||||
res = avb_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, pending->size);
|
||||
res = avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, pending->size);
|
||||
|
||||
pending_free(acmp, pending);
|
||||
|
||||
|
|
@ -271,22 +280,23 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
|||
static int handle_connect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
const struct avb_packet_acmp *p = m;
|
||||
struct avb_ethernet_header *h;
|
||||
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
|
||||
struct avb_packet_acmp *cmd;
|
||||
|
||||
if (be64toh(p->listener_guid) != server->entity_id)
|
||||
return 0;
|
||||
|
||||
cmd = pending_new(acmp, PENDING_TALKER, now,
|
||||
h = pending_new(acmp, PENDING_TALKER, now,
|
||||
AVB_ACMP_TIMEOUT_CONNECT_TX_COMMAND_MS, m, len);
|
||||
if (cmd == NULL)
|
||||
if (h == NULL)
|
||||
return -errno;
|
||||
|
||||
cmd = SPA_PTROFF(h, sizeof(*h), void);
|
||||
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_CONNECT_TX_COMMAND);
|
||||
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
|
||||
|
||||
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||
AVB_TSN_ETH, cmd, len);
|
||||
return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, len);
|
||||
}
|
||||
|
||||
static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
|
|
@ -297,22 +307,23 @@ static int handle_ignore(struct acmp *acmp, uint64_t now, const void *m, int len
|
|||
static int handle_disconnect_rx_command(struct acmp *acmp, uint64_t now, const void *m, int len)
|
||||
{
|
||||
struct server *server = acmp->server;
|
||||
const struct avb_packet_acmp *p = m;
|
||||
struct avb_ethernet_header *h;
|
||||
const struct avb_packet_acmp *p = SPA_PTROFF(m, sizeof(*h), void);
|
||||
struct avb_packet_acmp *cmd;
|
||||
|
||||
if (be64toh(p->listener_guid) != server->entity_id)
|
||||
return 0;
|
||||
|
||||
cmd = pending_new(acmp, PENDING_TALKER, now,
|
||||
h = pending_new(acmp, PENDING_TALKER, now,
|
||||
AVB_ACMP_TIMEOUT_DISCONNECT_TX_COMMAND_MS, m, len);
|
||||
if (cmd == NULL)
|
||||
if (h == NULL)
|
||||
return -errno;
|
||||
|
||||
cmd = SPA_PTROFF(h, sizeof(*h), void);
|
||||
AVB_PACKET_ACMP_SET_MESSAGE_TYPE(cmd, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_TX_COMMAND);
|
||||
AVB_PACKET_ACMP_SET_STATUS(cmd, AVB_ACMP_STATUS_SUCCESS);
|
||||
|
||||
return avb_server_send_packet(server, cmd->hdr.eth.dest,
|
||||
AVB_TSN_ETH, cmd, len);
|
||||
return avb_server_send_packet(server, h->dest, AVB_TSN_ETH, h, len);
|
||||
}
|
||||
|
||||
static const struct msg_info msg_info[] = {
|
||||
|
|
@ -347,14 +358,15 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|||
{
|
||||
struct acmp *acmp = data;
|
||||
struct server *server = acmp->server;
|
||||
const struct avb_packet_acmp *p = message;
|
||||
const struct avb_ethernet_header *h = message;
|
||||
const struct avb_packet_acmp *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
const struct msg_info *info;
|
||||
int message_type;
|
||||
|
||||
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH)
|
||||
if (ntohs(h->type) != AVB_TSN_ETH)
|
||||
return 0;
|
||||
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||
if (memcmp(h->dest, mac, 6) != 0 &&
|
||||
memcmp(h->dest, server->mac_addr, 6) != 0)
|
||||
return 0;
|
||||
|
||||
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ACMP)
|
||||
|
|
@ -369,9 +381,9 @@ static int acmp_message(void *data, uint64_t now, const void *message, int len)
|
|||
pw_log_info("got ACMP message %s", info->name);
|
||||
|
||||
if (info->handle == NULL)
|
||||
return reply_not_supported(acmp, message_type | 1, p, len);
|
||||
return reply_not_supported(acmp, message_type | 1, message, len);
|
||||
|
||||
return info->handle(acmp, now, p, len);
|
||||
return info->handle(acmp, now, message, len);
|
||||
}
|
||||
|
||||
static void acmp_destroy(void *data)
|
||||
|
|
|
|||
|
|
@ -35,9 +35,12 @@ static const uint8_t mac[6] = AVB_BROADCAST_MAC;
|
|||
|
||||
struct entity {
|
||||
struct spa_list link;
|
||||
struct avb_packet_adp packet;
|
||||
uint64_t entity_id;
|
||||
uint64_t last_time;
|
||||
int valid_time;
|
||||
unsigned advertise:1;
|
||||
size_t len;
|
||||
uint8_t buf[128];
|
||||
};
|
||||
|
||||
struct adp {
|
||||
|
|
@ -52,7 +55,7 @@ static struct entity *find_entity_by_id(struct adp *adp, uint64_t id)
|
|||
{
|
||||
struct entity *e;
|
||||
spa_list_for_each(e, &adp->entities, link)
|
||||
if (be64toh(e->packet.entity_id) == id)
|
||||
if (e->entity_id == id)
|
||||
return e;
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -64,31 +67,41 @@ static void entity_free(struct entity *e)
|
|||
|
||||
static int send_departing(struct adp *adp, uint64_t now, struct entity *e)
|
||||
{
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING);
|
||||
e->packet.available_index = htonl(adp->available_index++);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
||||
struct avb_ethernet_header *h = (void*)e->buf;
|
||||
struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_DEPARTING);
|
||||
p->available_index = htonl(adp->available_index++);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, e->buf, e->len);
|
||||
e->last_time = now;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_advertise(struct adp *adp, uint64_t now, struct entity *e)
|
||||
{
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&e->packet, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
||||
e->packet.available_index = htonl(adp->available_index++);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &e->packet, sizeof(e->packet));
|
||||
struct avb_ethernet_header *h = (void*)e->buf;
|
||||
struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
||||
p->available_index = htonl(adp->available_index++);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, e->buf, e->len);
|
||||
e->last_time = now;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_discover(struct adp *adp, uint64_t entity_id)
|
||||
{
|
||||
struct avb_packet_adp p;
|
||||
spa_zero(p);
|
||||
AVB_PACKET_SET_SUBTYPE(&p.hdr, AVB_SUBTYPE_ADP);
|
||||
AVB_PACKET_SET_LENGTH(&p.hdr, AVB_ADP_CONTROL_DATA_LENGTH);
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(&p, AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
|
||||
p.entity_id = htonl(entity_id);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, &p, sizeof(p));
|
||||
uint8_t buf[128];
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
size_t len = sizeof(*h) + sizeof(*p);
|
||||
|
||||
spa_memzero(buf, sizeof(buf));
|
||||
AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP);
|
||||
AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH);
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER);
|
||||
p->entity_id = htonl(entity_id);
|
||||
avb_server_send_packet(adp->server, mac, AVB_TSN_ETH, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -96,16 +109,17 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
|||
{
|
||||
struct adp *adp = data;
|
||||
struct server *server = adp->server;
|
||||
const struct avb_packet_adp *p = message;
|
||||
const struct avb_ethernet_header *h = message;
|
||||
const struct avb_packet_adp *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
struct entity *e;
|
||||
int message_type;
|
||||
char buf[128];
|
||||
uint64_t entity_id;
|
||||
|
||||
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH)
|
||||
if (ntohs(h->type) != AVB_TSN_ETH)
|
||||
return 0;
|
||||
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||
if (memcmp(h->dest, mac, 6) != 0 &&
|
||||
memcmp(h->dest, server->mac_addr, 6) != 0)
|
||||
return 0;
|
||||
|
||||
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_ADP ||
|
||||
|
|
@ -124,7 +138,10 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
|||
if (e == NULL)
|
||||
return -errno;
|
||||
|
||||
e->packet = *p;
|
||||
memcpy(e->buf, message, len);
|
||||
e->len = len;
|
||||
e->valid_time = AVB_PACKET_ADP_GET_VALID_TIME(p);
|
||||
e->entity_id = entity_id;
|
||||
spa_list_append(&adp->entities, &e->link);
|
||||
pw_log_info("entity %s available",
|
||||
avb_utils_format_id(buf, sizeof(buf), entity_id));
|
||||
|
|
@ -145,8 +162,8 @@ static int adp_message(void *data, uint64_t now, const void *message, int len)
|
|||
spa_list_for_each(e, &adp->entities, link)
|
||||
if (e->advertise)
|
||||
send_advertise(adp, now, e);
|
||||
} else if (e != NULL && e->advertise &&
|
||||
be64toh(e->packet.entity_id) == entity_id) {
|
||||
} else if (e != NULL &&
|
||||
e->advertise && e->entity_id == entity_id) {
|
||||
send_advertise(adp, now, e);
|
||||
}
|
||||
break;
|
||||
|
|
@ -169,14 +186,11 @@ static void check_timeout(struct adp *adp, uint64_t now)
|
|||
char buf[128];
|
||||
|
||||
spa_list_for_each_safe(e, t, &adp->entities, link) {
|
||||
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
||||
|
||||
if (e->last_time + (valid_time + 2) * SPA_NSEC_PER_SEC > now)
|
||||
if (e->last_time + (e->valid_time + 2) * SPA_NSEC_PER_SEC > now)
|
||||
continue;
|
||||
|
||||
pw_log_info("entity %s timeout",
|
||||
avb_utils_format_id(buf, sizeof(buf),
|
||||
be64toh(e->packet.entity_id)));
|
||||
avb_utils_format_id(buf, sizeof(buf), e->entity_id));
|
||||
|
||||
if (e->advertise)
|
||||
send_departing(adp, now, e);
|
||||
|
|
@ -186,18 +200,16 @@ static void check_timeout(struct adp *adp, uint64_t now)
|
|||
}
|
||||
static void check_readvertize(struct adp *adp, uint64_t now, struct entity *e)
|
||||
{
|
||||
int valid_time = AVB_PACKET_ADP_GET_VALID_TIME(&e->packet);
|
||||
char buf[128];
|
||||
|
||||
if (!e->advertise)
|
||||
return;
|
||||
|
||||
if (e->last_time + (valid_time / 2) * SPA_NSEC_PER_SEC > now)
|
||||
if (e->last_time + (e->valid_time / 2) * SPA_NSEC_PER_SEC > now)
|
||||
return;
|
||||
|
||||
pw_log_debug("entity %s readvertise",
|
||||
avb_utils_format_id(buf, sizeof(buf),
|
||||
be64toh(e->packet.entity_id)));
|
||||
avb_utils_format_id(buf, sizeof(buf), e->entity_id));
|
||||
|
||||
send_advertise(adp, now, e);
|
||||
}
|
||||
|
|
@ -210,6 +222,7 @@ static int check_advertise(struct adp *adp, uint64_t now)
|
|||
struct avb_aem_desc_avb_interface *avb_interface;
|
||||
struct entity *e;
|
||||
uint64_t entity_id;
|
||||
struct avb_ethernet_header *h;
|
||||
struct avb_packet_adp *p;
|
||||
char buf[128];
|
||||
|
||||
|
|
@ -237,13 +250,17 @@ static int check_advertise(struct adp *adp, uint64_t now)
|
|||
return -errno;
|
||||
|
||||
e->advertise = true;
|
||||
e->valid_time = 10;
|
||||
e->last_time = now;
|
||||
e->entity_id = entity_id;
|
||||
e->len = sizeof(*h) + sizeof(*p);
|
||||
|
||||
p = &e->packet;
|
||||
h = (void*)e->buf;
|
||||
p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
AVB_PACKET_SET_LENGTH(&p->hdr, AVB_ADP_CONTROL_DATA_LENGTH);
|
||||
AVB_PACKET_SET_SUBTYPE(&p->hdr, AVB_SUBTYPE_ADP);
|
||||
AVB_PACKET_ADP_SET_MESSAGE_TYPE(p, AVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE);
|
||||
AVB_PACKET_ADP_SET_VALID_TIME(p, 10);
|
||||
AVB_PACKET_ADP_SET_VALID_TIME(p, e->valid_time);
|
||||
|
||||
p->entity_id = entity->entity_id;
|
||||
p->entity_model_id = entity->entity_model_id;
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ static int reply_status(struct aecp *aecp, int status, const void *m, int len)
|
|||
{
|
||||
struct server *server = aecp->server;
|
||||
uint8_t buf[len];
|
||||
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf;
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_aecp_header *reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
memcpy(reply, m, len);
|
||||
memcpy(buf, m, len);
|
||||
AVB_PACKET_AECP_SET_MESSAGE_TYPE(reply, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||
AVB_PACKET_AECP_SET_STATUS(reply, status);
|
||||
|
||||
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||
AVB_TSN_ETH, reply, len);
|
||||
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
|
||||
}
|
||||
|
||||
static int reply_not_implemented(struct aecp *aecp, const void *m, int len)
|
||||
|
|
@ -101,7 +101,8 @@ static int handle_lock_entity(struct aecp *aecp, const void *m, int len)
|
|||
static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
|
||||
{
|
||||
struct server *server = aecp->server;
|
||||
const struct avb_packet_aecp_aem *p = m;
|
||||
const struct avb_ethernet_header *h = m;
|
||||
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
struct avb_packet_aecp_aem *reply;
|
||||
const struct avb_packet_aecp_aem_read_descriptor *rd;
|
||||
uint16_t desc_type, desc_id;
|
||||
|
|
@ -118,31 +119,32 @@ static int handle_read_descriptor(struct aecp *aecp, const void *m, int len)
|
|||
|
||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||
if (desc == NULL)
|
||||
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
|
||||
|
||||
memcpy(buf, p, len);
|
||||
memcpy(buf, m, len);
|
||||
|
||||
psize = sizeof(*rd);
|
||||
size = sizeof(*reply) + psize;
|
||||
size = sizeof(*h) + sizeof(*reply) + psize;
|
||||
|
||||
memcpy(buf + size, desc->ptr, desc->size);
|
||||
size += desc->size;
|
||||
psize += desc->size;
|
||||
|
||||
reply = (struct avb_packet_aecp_aem*)buf;
|
||||
h = (void*)buf;
|
||||
reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
|
||||
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
||||
|
||||
return avb_server_send_packet(server, reply->aecp.hdr.eth.src,
|
||||
AVB_TSN_ETH, reply, size);
|
||||
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size);
|
||||
}
|
||||
|
||||
/* GET_AVB_INFO */
|
||||
static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
|
||||
{
|
||||
struct server *server = aecp->server;
|
||||
const struct avb_packet_aecp_aem *p = m;
|
||||
const struct avb_ethernet_header *h = m;
|
||||
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
struct avb_packet_aecp_aem *reply;
|
||||
struct avb_packet_aecp_aem_get_avb_info *i;
|
||||
struct avb_aem_desc_avb_interface *avb_interface;
|
||||
|
|
@ -158,19 +160,20 @@ static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
|
|||
|
||||
desc = server_find_descriptor(server, desc_type, desc_id);
|
||||
if (desc == NULL)
|
||||
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, p, len);
|
||||
return reply_status(aecp, AVB_AECP_AEM_STATUS_NO_SUCH_DESCRIPTOR, m, len);
|
||||
|
||||
if (desc_type != AVB_AEM_DESC_AVB_INTERFACE || desc_id != 0)
|
||||
return reply_not_implemented(aecp, m, len);
|
||||
|
||||
avb_interface = desc->ptr;
|
||||
|
||||
memcpy(buf, p, len);
|
||||
memcpy(buf, m, len);
|
||||
|
||||
psize = sizeof(*i);
|
||||
size = sizeof(*reply) + psize;
|
||||
size = sizeof(*h) + sizeof(*reply) + psize;
|
||||
|
||||
reply = (struct avb_packet_aecp_aem *)buf;
|
||||
h = (void*)buf;
|
||||
reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
AVB_PACKET_AECP_SET_MESSAGE_TYPE(&reply->aecp, AVB_AECP_MESSAGE_TYPE_AEM_RESPONSE);
|
||||
AVB_PACKET_AECP_SET_STATUS(&reply->aecp, AVB_AECP_AEM_STATUS_SUCCESS);
|
||||
AVB_PACKET_SET_LENGTH(&reply->aecp.hdr, psize + 12);
|
||||
|
|
@ -182,8 +185,7 @@ static int handle_get_avb_info(struct aecp *aecp, const void *m, int len)
|
|||
i->flags = 0;
|
||||
i->msrp_mappings_count = htons(0);
|
||||
|
||||
return avb_server_send_packet(server, reply->aecp.hdr.eth.src,
|
||||
AVB_TSN_ETH, reply, size);
|
||||
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, size);
|
||||
}
|
||||
|
||||
/* AEM_COMMAND */
|
||||
|
|
@ -259,7 +261,8 @@ static inline const struct cmd_info *find_cmd_info(uint16_t type, const char *na
|
|||
|
||||
int avb_aecp_aem_handle_command(struct aecp *aecp, const void *m, int len)
|
||||
{
|
||||
const struct avb_packet_aecp_aem *p = m;
|
||||
const struct avb_ethernet_header *h = m;
|
||||
const struct avb_packet_aecp_aem *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
uint16_t cmd_type;
|
||||
const struct cmd_info *info;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ static int reply_not_implemented(struct aecp *aecp, const void *p, int len)
|
|||
{
|
||||
struct server *server = aecp->server;
|
||||
uint8_t buf[len];
|
||||
struct avb_packet_aecp_header *reply = (struct avb_packet_aecp_header*)buf;
|
||||
struct avb_ethernet_header *h = (void*)buf;
|
||||
struct avb_packet_aecp_header *reply = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
memcpy(reply, p, len);
|
||||
memcpy(h, p, len);
|
||||
AVB_PACKET_AECP_SET_STATUS(reply, AVB_AECP_STATUS_NOT_IMPLEMENTED);
|
||||
|
||||
return avb_server_send_packet(server, reply->hdr.eth.src,
|
||||
AVB_TSN_ETH, reply, len);
|
||||
return avb_server_send_packet(server, h->src, AVB_TSN_ETH, buf, len);
|
||||
}
|
||||
|
||||
static const struct msg_info msg_info[] = {
|
||||
|
|
@ -80,14 +80,15 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
|
|||
{
|
||||
struct aecp *aecp = data;
|
||||
struct server *server = aecp->server;
|
||||
const struct avb_packet_aecp_header *p = message;
|
||||
const struct avb_ethernet_header *h = message;
|
||||
const struct avb_packet_aecp_header *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
const struct msg_info *info;
|
||||
int message_type;
|
||||
|
||||
if (ntohs(p->hdr.eth.type) != AVB_TSN_ETH)
|
||||
if (ntohs(h->type) != AVB_TSN_ETH)
|
||||
return 0;
|
||||
if (memcmp(p->hdr.eth.dest, mac, 6) != 0 &&
|
||||
memcmp(p->hdr.eth.dest, server->mac_addr, 6) != 0)
|
||||
if (memcmp(h->dest, mac, 6) != 0 &&
|
||||
memcmp(h->dest, server->mac_addr, 6) != 0)
|
||||
return 0;
|
||||
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_AECP)
|
||||
return 0;
|
||||
|
|
@ -96,14 +97,14 @@ static int aecp_message(void *data, uint64_t now, const void *message, int len)
|
|||
|
||||
info = find_msg_info(message_type, NULL);
|
||||
if (info == NULL)
|
||||
return reply_not_implemented(aecp, p, len);
|
||||
return reply_not_implemented(aecp, message, len);
|
||||
|
||||
pw_log_debug("got AECP message %s", info->name);
|
||||
|
||||
if (info->handle == NULL)
|
||||
return reply_not_implemented(aecp, p, len);
|
||||
return reply_not_implemented(aecp, message, len);
|
||||
|
||||
return info->handle(aecp, p, len);
|
||||
return info->handle(aecp, message, len);
|
||||
}
|
||||
|
||||
static void aecp_destroy(void *data)
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ struct pw_avb *pw_avb_new(struct pw_context *context,
|
|||
|
||||
spa_list_init(&impl->servers);
|
||||
|
||||
avdecc_server_new(impl, pw_properties_get(props, "ifname"), NULL);
|
||||
avdecc_server_new(impl, &props->dict);
|
||||
|
||||
return (struct pw_avb*)impl;
|
||||
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ error_no_source:
|
|||
return res;
|
||||
}
|
||||
|
||||
struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct spa_dict *props)
|
||||
struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props)
|
||||
{
|
||||
struct server *server;
|
||||
int res = 0;
|
||||
|
|
@ -268,7 +268,7 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
|
|||
|
||||
server->impl = impl;
|
||||
spa_list_append(&impl->servers, &server->link);
|
||||
server->ifname = strdup(ifname);
|
||||
server->ifname = strdup(spa_dict_lookup(props, "ifname"));
|
||||
spa_hook_list_init(&server->listener_list);
|
||||
spa_list_init(&server->descriptors);
|
||||
spa_list_init(&server->streams);
|
||||
|
|
@ -294,9 +294,9 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
|
|||
|
||||
server->domain_attr = avb_msrp_attribute_new(server->msrp,
|
||||
AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN);
|
||||
server->domain_attr->attr.domain.sr_class_id = 6;
|
||||
server->domain_attr->attr.domain.sr_class_priority = 3;
|
||||
server->domain_attr->attr.domain.sr_class_vid = htons(2);
|
||||
server->domain_attr->attr.domain.sr_class_id = AVB_MSRP_CLASS_ID_DEFAULT;
|
||||
server->domain_attr->attr.domain.sr_class_priority = AVB_MSRP_PRIORITY_DEFAULT;
|
||||
server->domain_attr->attr.domain.sr_class_vid = htons(AVB_DEFAULT_VLAN);
|
||||
|
||||
avb_mrp_attribute_begin(server->domain_attr->mrp, 0);
|
||||
avb_mrp_attribute_join(server->domain_attr->mrp, 0, true);
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
#include "packets.h"
|
||||
|
||||
struct avb_packet_iec61883 {
|
||||
struct avb_ethernet_header eth;
|
||||
uint32_t vlan;
|
||||
uint8_t subtype;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sv:1;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ static inline struct stream *server_find_stream(struct server *server,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct spa_dict *props);
|
||||
struct server *avdecc_server_new(struct impl *impl, struct spa_dict *props);
|
||||
void avdecc_server_free(struct server *server);
|
||||
|
||||
void avdecc_server_add_listener(struct server *server, struct spa_hook *listener,
|
||||
|
|
|
|||
|
|
@ -148,37 +148,43 @@ static uint16_t maap_check_conflict(struct maap *maap, const uint8_t request_sta
|
|||
static int send_packet(struct maap *maap, uint64_t now,
|
||||
uint8_t type, const uint8_t conflict_start[6], uint16_t conflict_count)
|
||||
{
|
||||
struct avb_packet_maap p;
|
||||
struct avb_ethernet_header *h;
|
||||
struct avb_packet_maap *p;
|
||||
uint8_t buf[1024];
|
||||
uint8_t bmac[6] = AVB_MAAP_MAC;
|
||||
int res = 0;
|
||||
uint8_t start[6];
|
||||
|
||||
spa_zero(p);
|
||||
memcpy(p.hdr.eth.dest, bmac, 6);
|
||||
memcpy(p.hdr.eth.src, maap->server->mac_addr, 6);
|
||||
p.hdr.eth.type = htons(AVB_TSN_ETH);
|
||||
p.hdr.subtype = AVB_SUBTYPE_MAAP;
|
||||
AVB_PACKET_SET_LENGTH(&p.hdr, sizeof(p) - sizeof(p.hdr.eth));
|
||||
spa_memzero(buf, sizeof(buf));
|
||||
h = (void*)buf;
|
||||
p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
AVB_PACKET_MAAP_SET_MAAP_VERSION(&p, 1);
|
||||
AVB_PACKET_MAAP_SET_MESSAGE_TYPE(&p, type);
|
||||
memcpy(h->dest, bmac, 6);
|
||||
memcpy(h->src, maap->server->mac_addr, 6);
|
||||
h->type = htons(AVB_TSN_ETH);
|
||||
|
||||
p->hdr.subtype = AVB_SUBTYPE_MAAP;
|
||||
AVB_PACKET_SET_LENGTH(&p->hdr, sizeof(*p));
|
||||
|
||||
AVB_PACKET_MAAP_SET_MAAP_VERSION(p, 1);
|
||||
AVB_PACKET_MAAP_SET_MESSAGE_TYPE(p, type);
|
||||
|
||||
memcpy(start, maap_base, 4);
|
||||
start[4] = maap->offset >> 8;
|
||||
start[5] = maap->offset;
|
||||
AVB_PACKET_MAAP_SET_REQUEST_START(&p, start);
|
||||
AVB_PACKET_MAAP_SET_REQUEST_COUNT(&p, maap->count);
|
||||
AVB_PACKET_MAAP_SET_REQUEST_START(p, start);
|
||||
AVB_PACKET_MAAP_SET_REQUEST_COUNT(p, maap->count);
|
||||
if (conflict_count) {
|
||||
AVB_PACKET_MAAP_SET_CONFLICT_START(&p, conflict_start);
|
||||
AVB_PACKET_MAAP_SET_CONFLICT_COUNT(&p, conflict_count);
|
||||
AVB_PACKET_MAAP_SET_CONFLICT_START(p, conflict_start);
|
||||
AVB_PACKET_MAAP_SET_CONFLICT_COUNT(p, conflict_count);
|
||||
}
|
||||
|
||||
if (maap->server->debug_messages) {
|
||||
pw_log_info("send: %d (%s)", type, message_type_as_string(type));
|
||||
maap_message_debug(maap, &p);
|
||||
maap_message_debug(maap, p);
|
||||
}
|
||||
|
||||
if (send(maap->source->fd, &p, sizeof(p), 0) < 0) {
|
||||
if (send(maap->source->fd, p, sizeof(*h) + sizeof(*p), 0) < 0) {
|
||||
res = -errno;
|
||||
pw_log_warn("got send error: %m");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,9 +202,9 @@ static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
|
|||
static void debug_msrp_domain(const struct avb_packet_msrp_domain *d)
|
||||
{
|
||||
pw_log_info("domain");
|
||||
pw_log_info(" %d", d->sr_class_id);
|
||||
pw_log_info(" %d", d->sr_class_priority);
|
||||
pw_log_info(" %d", ntohs(d->sr_class_vid));
|
||||
pw_log_info(" id: %d", d->sr_class_id);
|
||||
pw_log_info(" prio: %d", d->sr_class_priority);
|
||||
pw_log_info(" vid: %d", ntohs(d->sr_class_vid));
|
||||
}
|
||||
|
||||
static void notify_domain(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,9 @@ struct avb_packet_msrp_listener {
|
|||
} __attribute__ ((__packed__));
|
||||
|
||||
/* domain discovery */
|
||||
#define AVB_MSRP_CLASS_ID_DEFAULT 6
|
||||
#define AVB_DEFAULT_VLAN 2
|
||||
|
||||
struct avb_packet_msrp_domain {
|
||||
uint8_t sr_class_id;
|
||||
uint8_t sr_class_priority;
|
||||
|
|
|
|||
|
|
@ -54,8 +54,15 @@ struct avb_ethernet_header {
|
|||
uint16_t type;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct avb_frame_header {
|
||||
uint8_t dest[6];
|
||||
uint8_t src[6];
|
||||
uint16_t type; /* 802.1Q Virtual Lan 0x8100 */
|
||||
uint16_t prio_cfi_id;
|
||||
uint16_t etype;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
struct avb_packet_header {
|
||||
struct avb_ethernet_header eth;
|
||||
uint8_t subtype;
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sv:1; /* stream_id valid */
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ static void on_source_stream_process(void *data)
|
|||
avail = spa_ringbuffer_get_read_index(&stream->ring, &index);
|
||||
|
||||
if (avail < wanted) {
|
||||
pw_log_warn("capture underrun %d < %d", avail, wanted);
|
||||
pw_log_debug("capture underrun %d < %d", avail, wanted);
|
||||
memset(d[0].data, 0, n_bytes);
|
||||
} else {
|
||||
spa_ringbuffer_read_data(&stream->ring,
|
||||
|
|
@ -110,7 +110,8 @@ static int flush_write(struct stream *stream, uint64_t current_time)
|
|||
uint64_t ptime, txtime;
|
||||
int pdu_count;
|
||||
ssize_t n;
|
||||
struct avb_packet_iec61883 *p = (struct avb_packet_iec61883*)stream->pdu;
|
||||
struct avb_frame_header *h = (void*)stream->pdu;
|
||||
struct avb_packet_iec61883 *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
avail = spa_ringbuffer_get_read_index(&stream->ring, &index);
|
||||
|
||||
|
|
@ -186,16 +187,21 @@ static void on_sink_stream_process(void *data)
|
|||
|
||||
static void setup_pdu(struct stream *stream)
|
||||
{
|
||||
struct avb_packet_iec61883 *p = (struct avb_packet_iec61883*)stream->pdu;
|
||||
struct avb_frame_header *h;
|
||||
struct avb_packet_iec61883 *p;
|
||||
ssize_t payload_size, hdr_size, pdu_size;
|
||||
|
||||
hdr_size = sizeof(*p);
|
||||
spa_memzero(stream->pdu, sizeof(stream->pdu));
|
||||
h = (struct avb_frame_header*)stream->pdu;
|
||||
p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
hdr_size = sizeof(*h) + sizeof(*p);
|
||||
payload_size = stream->stride * stream->frames_per_pdu;
|
||||
pdu_size = hdr_size + payload_size;
|
||||
|
||||
spa_zero(stream->pdu);
|
||||
p->eth.type = htons(0x8100);
|
||||
p->vlan = htonl(0x600222f0);
|
||||
h->type = htons(0x8100);
|
||||
h->prio_cfi_id = htons((stream->prio << 13) | stream->vlan_id);
|
||||
h->etype = htons(0x22f0);
|
||||
|
||||
if (stream->direction == SPA_DIRECTION_OUTPUT) {
|
||||
p->subtype = AVB_SUBTYPE_61883_IIDC;
|
||||
|
|
@ -272,6 +278,9 @@ struct stream *server_create_stream(struct server *server,
|
|||
stream->desc = desc;
|
||||
spa_list_append(&server->streams, &stream->link);
|
||||
|
||||
stream->prio = AVB_MSRP_PRIORITY_DEFAULT;
|
||||
stream->vlan_id = AVB_DEFAULT_VLAN;
|
||||
|
||||
stream->id = (uint64_t)server->mac_addr[0] << 56 |
|
||||
(uint64_t)server->mac_addr[1] << 48 |
|
||||
(uint64_t)server->mac_addr[2] << 40 |
|
||||
|
|
@ -284,16 +293,16 @@ struct stream *server_create_stream(struct server *server,
|
|||
AVB_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
||||
stream->talker_attr = avb_msrp_attribute_new(server->msrp,
|
||||
AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE);
|
||||
stream->talker_attr->attr.talker.vlan_id = htons(2);
|
||||
stream->talker_attr->attr.talker.vlan_id = htons(stream->vlan_id);
|
||||
stream->talker_attr->attr.talker.tspec_max_interval_frames =
|
||||
htons(AVB_MSRP_TSPEC_MAX_INTERVAL_FRAMES_DEFAULT);
|
||||
stream->talker_attr->attr.talker.priority = AVB_MSRP_PRIORITY_DEFAULT;
|
||||
stream->talker_attr->attr.talker.priority = stream->prio;
|
||||
stream->talker_attr->attr.talker.rank = AVB_MSRP_RANK_DEFAULT;
|
||||
stream->talker_attr->attr.talker.accumulated_latency = 0;
|
||||
|
||||
stream->vlan_attr = avb_mvrp_attribute_new(server->mvrp,
|
||||
AVB_MVRP_ATTRIBUTE_TYPE_VID);
|
||||
stream->vlan_attr->attr.vid.vlan = htons(2);
|
||||
stream->vlan_attr->attr.vid.vlan = htons(stream->vlan_id);
|
||||
|
||||
stream->buffer_data = calloc(1, BUFFER_SIZE);
|
||||
stream->buffer_size = BUFFER_SIZE;
|
||||
|
|
@ -455,14 +464,13 @@ static void handle_iec61883_packet(struct stream *stream,
|
|||
{
|
||||
uint32_t index, n_bytes;
|
||||
int32_t filled;
|
||||
bool overrun = false;
|
||||
|
||||
filled = spa_ringbuffer_get_write_index(&stream->ring, &index);
|
||||
overrun = filled > (int32_t) stream->buffer_size;
|
||||
if (overrun) {
|
||||
pw_log_warn("capture overrun %zd < %d", stream->buffer_size, filled);
|
||||
} else {
|
||||
n_bytes = ntohs(p->data_len) - 8;
|
||||
|
||||
if (filled + n_bytes > stream->buffer_size) {
|
||||
pw_log_debug("capture overrun");
|
||||
} else {
|
||||
spa_ringbuffer_write_data(&stream->ring,
|
||||
stream->buffer_data,
|
||||
stream->buffer_size,
|
||||
|
|
@ -471,7 +479,6 @@ static void handle_iec61883_packet(struct stream *stream,
|
|||
index += n_bytes;
|
||||
spa_ringbuffer_write_update(&stream->ring, index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void on_socket_data(void *data, int fd, uint32_t mask)
|
||||
|
|
@ -491,13 +498,14 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
|
|||
pw_log_warn("short packet received (%d < %d)", len,
|
||||
(int)sizeof(struct avb_packet_header));
|
||||
} else {
|
||||
struct avb_packet_iec61883 *h = (struct avb_packet_iec61883*)buffer;
|
||||
struct avb_frame_header *h = (void*)buffer;
|
||||
struct avb_packet_iec61883 *p = SPA_PTROFF(h, sizeof(*h), void);
|
||||
|
||||
if (memcmp(h->eth.dest, stream->addr, 6) != 0 ||
|
||||
h->subtype != AVB_SUBTYPE_61883_IIDC)
|
||||
if (memcmp(h->dest, stream->addr, 6) != 0 ||
|
||||
p->subtype != AVB_SUBTYPE_61883_IIDC)
|
||||
return;
|
||||
|
||||
handle_iec61883_packet(stream, h, len);
|
||||
handle_iec61883_packet(stream, p, len - sizeof(*h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -505,7 +513,7 @@ static void on_socket_data(void *data, int fd, uint32_t mask)
|
|||
int stream_activate(struct stream *stream, uint64_t now)
|
||||
{
|
||||
struct server *server = stream->server;
|
||||
struct avb_ethernet_header *h = (struct avb_ethernet_header *)stream->pdu;
|
||||
struct avb_frame_header *h = (void*)stream->pdu;
|
||||
int fd, res;
|
||||
|
||||
if (stream->source == NULL) {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ struct stream {
|
|||
uint8_t addr[6];
|
||||
struct spa_source *source;
|
||||
int prio;
|
||||
int vlan_id;
|
||||
int mtt;
|
||||
int t_uncertainty;
|
||||
uint32_t frames_per_pdu;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue