2023-02-08 18:12:00 +01:00
|
|
|
/* AVB support */
|
|
|
|
|
/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */
|
|
|
|
|
/* SPDX-License-Identifier: MIT */
|
2022-03-15 18:16:00 +01:00
|
|
|
|
2022-04-03 17:52:28 +02:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
#include <spa/utils/json.h>
|
|
|
|
|
|
2022-03-15 18:16:00 +01:00
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
#include "utils.h"
|
2022-03-15 18:16:00 +01:00
|
|
|
#include "maap.h"
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
#define MAAP_ALLOCATION_POOL_SIZE 0xFE00
|
|
|
|
|
#define MAAP_ALLOCATION_POOL_BASE { 0x91, 0xe0, 0xf0, 0x00, 0x00, 0x00 }
|
|
|
|
|
static uint8_t maap_base[6] = MAAP_ALLOCATION_POOL_BASE;
|
|
|
|
|
|
|
|
|
|
#define MAAP_PROBE_RETRANSMITS 3
|
|
|
|
|
|
|
|
|
|
#define MAAP_PROBE_INTERVAL_MS 500
|
|
|
|
|
#define MAAP_PROBE_INTERVAL_VAR_MS 100
|
|
|
|
|
|
|
|
|
|
#define MAAP_ANNOUNCE_INTERVAL_MS 3000
|
|
|
|
|
#define MAAP_ANNOUNCE_INTERVAL_VAR_MS 2000
|
|
|
|
|
|
2022-03-15 18:16:00 +01:00
|
|
|
struct maap {
|
|
|
|
|
struct server *server;
|
|
|
|
|
struct spa_hook server_listener;
|
2022-04-03 12:32:25 +02:00
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
struct pw_properties *props;
|
|
|
|
|
|
2022-04-03 12:32:25 +02:00
|
|
|
struct spa_source *source;
|
2022-04-06 12:58:47 +02:00
|
|
|
|
|
|
|
|
#define STATE_IDLE 0
|
|
|
|
|
#define STATE_PROBE 1
|
|
|
|
|
#define STATE_ANNOUNCE 2
|
|
|
|
|
uint32_t state;
|
|
|
|
|
uint64_t timeout;
|
|
|
|
|
uint32_t probe_count;
|
|
|
|
|
|
|
|
|
|
unsigned short xsubi[3];
|
|
|
|
|
|
|
|
|
|
uint16_t offset;
|
|
|
|
|
uint16_t count;
|
2022-03-15 18:16:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char *message_type_as_string(uint8_t message_type)
|
|
|
|
|
{
|
|
|
|
|
switch (message_type) {
|
2022-03-25 10:28:18 +01:00
|
|
|
case AVB_MAAP_MESSAGE_TYPE_PROBE:
|
2022-03-15 18:16:00 +01:00
|
|
|
return "PROBE";
|
2022-03-25 10:28:18 +01:00
|
|
|
case AVB_MAAP_MESSAGE_TYPE_DEFEND:
|
2022-03-15 18:16:00 +01:00
|
|
|
return "DEFEND";
|
2022-03-25 10:28:18 +01:00
|
|
|
case AVB_MAAP_MESSAGE_TYPE_ANNOUNCE:
|
2022-03-15 18:16:00 +01:00
|
|
|
return "ANNOUNCE";
|
|
|
|
|
}
|
|
|
|
|
return "INVALID";
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
static void maap_message_debug(struct maap *maap, const struct avb_packet_maap *p)
|
2022-03-15 18:16:00 +01:00
|
|
|
{
|
|
|
|
|
uint32_t v;
|
|
|
|
|
const uint8_t *addr;
|
|
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
v = AVB_PACKET_MAAP_GET_MESSAGE_TYPE(p);
|
2022-03-15 18:16:00 +01:00
|
|
|
pw_log_info("message-type: %d (%s)", v, message_type_as_string(v));
|
2022-03-25 10:28:18 +01:00
|
|
|
pw_log_info(" maap-version: %d", AVB_PACKET_MAAP_GET_MAAP_VERSION(p));
|
|
|
|
|
pw_log_info(" length: %d", AVB_PACKET_GET_LENGTH(&p->hdr));
|
2022-03-15 18:16:00 +01:00
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
pw_log_info(" stream-id: 0x%"PRIx64, AVB_PACKET_MAAP_GET_STREAM_ID(p));
|
|
|
|
|
addr = AVB_PACKET_MAAP_GET_REQUEST_START(p);
|
2022-03-15 18:16:00 +01:00
|
|
|
pw_log_info(" request-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
2022-03-25 10:28:18 +01:00
|
|
|
pw_log_info(" request-count: %d", AVB_PACKET_MAAP_GET_REQUEST_COUNT(p));
|
|
|
|
|
addr = AVB_PACKET_MAAP_GET_CONFLICT_START(p);
|
2022-03-15 18:16:00 +01:00
|
|
|
pw_log_info(" conflict-start: %02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
|
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
2022-03-25 10:28:18 +01:00
|
|
|
pw_log_info(" conflict-count: %d", AVB_PACKET_MAAP_GET_CONFLICT_COUNT(p));
|
2022-03-15 18:16:00 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
#define PROBE_TIMEOUT(n) ((n) + (MAAP_PROBE_INTERVAL_MS + \
|
|
|
|
|
drand48() * MAAP_PROBE_INTERVAL_VAR_MS) * SPA_NSEC_PER_MSEC)
|
|
|
|
|
#define ANNOUNCE_TIMEOUT(n) ((n) + (MAAP_ANNOUNCE_INTERVAL_MS + \
|
|
|
|
|
drand48() * MAAP_ANNOUNCE_INTERVAL_VAR_MS) * SPA_NSEC_PER_MSEC)
|
|
|
|
|
|
|
|
|
|
static int make_new_address(struct maap *maap, uint64_t now, int range)
|
|
|
|
|
{
|
|
|
|
|
maap->offset = nrand48(maap->xsubi) % (MAAP_ALLOCATION_POOL_SIZE - range);
|
|
|
|
|
maap->count = range;
|
|
|
|
|
maap->state = STATE_PROBE;
|
|
|
|
|
maap->probe_count = MAAP_PROBE_RETRANSMITS;
|
|
|
|
|
maap->timeout = PROBE_TIMEOUT(now);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint16_t maap_check_conflict(struct maap *maap, const uint8_t request_start[6],
|
|
|
|
|
uint16_t request_count, uint8_t conflict_start[6])
|
|
|
|
|
{
|
|
|
|
|
uint16_t our_start, our_end;
|
|
|
|
|
uint16_t req_start, req_end;
|
|
|
|
|
uint16_t conf_start, conf_count = 0;
|
|
|
|
|
|
|
|
|
|
if (memcmp(request_start, maap_base, 4) != 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
our_start = maap->offset;
|
|
|
|
|
our_end = our_start + maap->count;
|
|
|
|
|
req_start = request_start[4] << 8 | request_start[5];
|
|
|
|
|
req_end = req_start + request_count;
|
|
|
|
|
|
|
|
|
|
if (our_start >= req_start && our_start <= req_end) {
|
|
|
|
|
conf_start = our_start;
|
|
|
|
|
conf_count = SPA_MIN(our_end, req_end) - our_start;
|
|
|
|
|
}
|
|
|
|
|
else if (req_start >= our_start && req_start <= our_end) {
|
|
|
|
|
conf_start = req_start;
|
|
|
|
|
conf_count = SPA_MIN(req_end, our_end) - req_start;
|
|
|
|
|
}
|
|
|
|
|
if (conf_count == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
conflict_start[4] = conf_start >> 8;
|
|
|
|
|
conflict_start[5] = conf_start;
|
|
|
|
|
return conf_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int send_packet(struct maap *maap, uint64_t now,
|
|
|
|
|
uint8_t type, const uint8_t conflict_start[6], uint16_t conflict_count)
|
|
|
|
|
{
|
2022-04-07 15:14:45 +02:00
|
|
|
struct avb_ethernet_header *h;
|
|
|
|
|
struct avb_packet_maap *p;
|
|
|
|
|
uint8_t buf[1024];
|
2022-04-06 12:58:47 +02:00
|
|
|
uint8_t bmac[6] = AVB_MAAP_MAC;
|
|
|
|
|
int res = 0;
|
|
|
|
|
uint8_t start[6];
|
|
|
|
|
|
2022-04-07 15:14:45 +02:00
|
|
|
spa_memzero(buf, sizeof(buf));
|
|
|
|
|
h = (void*)buf;
|
|
|
|
|
p = SPA_PTROFF(h, sizeof(*h), void);
|
2022-04-06 12:58:47 +02:00
|
|
|
|
2022-04-07 15:14:45 +02:00
|
|
|
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);
|
2022-04-06 12:58:47 +02:00
|
|
|
|
|
|
|
|
memcpy(start, maap_base, 4);
|
|
|
|
|
start[4] = maap->offset >> 8;
|
|
|
|
|
start[5] = maap->offset;
|
2022-04-07 15:14:45 +02:00
|
|
|
AVB_PACKET_MAAP_SET_REQUEST_START(p, start);
|
|
|
|
|
AVB_PACKET_MAAP_SET_REQUEST_COUNT(p, maap->count);
|
2022-04-06 12:58:47 +02:00
|
|
|
if (conflict_count) {
|
2022-04-07 15:14:45 +02:00
|
|
|
AVB_PACKET_MAAP_SET_CONFLICT_START(p, conflict_start);
|
|
|
|
|
AVB_PACKET_MAAP_SET_CONFLICT_COUNT(p, conflict_count);
|
2022-04-06 12:58:47 +02:00
|
|
|
}
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
if (maap->server->debug_messages) {
|
|
|
|
|
pw_log_info("send: %d (%s)", type, message_type_as_string(type));
|
2022-04-07 15:14:45 +02:00
|
|
|
maap_message_debug(maap, p);
|
2022-04-06 15:37:42 +02:00
|
|
|
}
|
2022-04-06 12:58:47 +02:00
|
|
|
|
2022-04-07 15:14:45 +02:00
|
|
|
if (send(maap->source->fd, p, sizeof(*h) + sizeof(*p), 0) < 0) {
|
2022-04-06 12:58:47 +02:00
|
|
|
res = -errno;
|
|
|
|
|
pw_log_warn("got send error: %m");
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int handle_probe(struct maap *maap, uint64_t now, const struct avb_packet_maap *p)
|
|
|
|
|
{
|
|
|
|
|
uint8_t conflict_start[6];
|
|
|
|
|
uint16_t conflict_count;
|
|
|
|
|
|
|
|
|
|
conflict_count = maap_check_conflict(maap, p->request_start, ntohs(p->request_count),
|
|
|
|
|
conflict_start);
|
|
|
|
|
if (conflict_count == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
switch (maap->state) {
|
|
|
|
|
case STATE_PROBE:
|
|
|
|
|
make_new_address(maap, now, 8);
|
|
|
|
|
break;
|
|
|
|
|
case STATE_ANNOUNCE:
|
|
|
|
|
send_packet(maap, now, AVB_MAAP_MESSAGE_TYPE_DEFEND, conflict_start, conflict_count);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int handle_defend(struct maap *maap, uint64_t now, const struct avb_packet_maap *p)
|
|
|
|
|
{
|
|
|
|
|
uint8_t conflict_start[6];
|
|
|
|
|
uint16_t conflict_count;
|
|
|
|
|
|
|
|
|
|
conflict_count = maap_check_conflict(maap, p->conflict_start, ntohs(p->conflict_count),
|
|
|
|
|
conflict_start);
|
|
|
|
|
if (conflict_count != 0)
|
|
|
|
|
make_new_address(maap, now, 8);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-03 12:32:25 +02:00
|
|
|
static int maap_message(struct maap *maap, uint64_t now, const void *message, int len)
|
2022-03-15 18:16:00 +01:00
|
|
|
{
|
2022-03-25 10:28:18 +01:00
|
|
|
const struct avb_packet_maap *p = message;
|
2022-03-15 18:16:00 +01:00
|
|
|
|
2022-03-25 10:28:18 +01:00
|
|
|
if (AVB_PACKET_GET_SUBTYPE(&p->hdr) != AVB_SUBTYPE_MAAP)
|
2022-03-15 18:16:00 +01:00
|
|
|
return 0;
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
if (maap->server->debug_messages)
|
|
|
|
|
maap_message_debug(maap, p);
|
2022-03-15 18:16:00 +01:00
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
switch (AVB_PACKET_MAAP_GET_MESSAGE_TYPE(p)) {
|
|
|
|
|
case AVB_MAAP_MESSAGE_TYPE_PROBE:
|
|
|
|
|
handle_probe(maap, now, p);
|
|
|
|
|
break;
|
|
|
|
|
case AVB_MAAP_MESSAGE_TYPE_DEFEND:
|
|
|
|
|
case AVB_MAAP_MESSAGE_TYPE_ANNOUNCE:
|
|
|
|
|
handle_defend(maap, now, p);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-03-15 18:16:00 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-03 12:32:25 +02:00
|
|
|
static void on_socket_data(void *data, int fd, uint32_t mask)
|
|
|
|
|
{
|
|
|
|
|
struct maap *maap = data;
|
|
|
|
|
struct timespec now;
|
|
|
|
|
|
|
|
|
|
if (mask & SPA_IO_IN) {
|
|
|
|
|
int len;
|
|
|
|
|
uint8_t buffer[2048];
|
|
|
|
|
|
|
|
|
|
len = recv(fd, buffer, sizeof(buffer), 0);
|
|
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
pw_log_warn("got recv error: %m");
|
|
|
|
|
}
|
|
|
|
|
else if (len < (int)sizeof(struct avb_packet_header)) {
|
|
|
|
|
pw_log_warn("short packet received (%d < %d)", len,
|
|
|
|
|
(int)sizeof(struct avb_packet_header));
|
|
|
|
|
} else {
|
|
|
|
|
clock_gettime(CLOCK_REALTIME, &now);
|
|
|
|
|
maap_message(maap, SPA_TIMESPEC_TO_NSEC(&now), buffer, len);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
static int load_state(struct maap *maap)
|
|
|
|
|
{
|
|
|
|
|
const char *str;
|
|
|
|
|
char key[512];
|
|
|
|
|
struct spa_json it[3];
|
|
|
|
|
bool have_offset = false;
|
|
|
|
|
int count = 0, offset = 0;
|
|
|
|
|
|
|
|
|
|
snprintf(key, sizeof(key), "maap.%s", maap->server->ifname);
|
|
|
|
|
pw_conf_load_state("module-avb", key, maap->props);
|
|
|
|
|
|
|
|
|
|
if ((str = pw_properties_get(maap->props, "maap.addresses")) == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
spa_json_init(&it[0], str, strlen(str));
|
|
|
|
|
if (spa_json_enter_array(&it[0], &it[1]) <= 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (spa_json_enter_object(&it[1], &it[2]) <= 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) {
|
|
|
|
|
const char *val;
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
if ((len = spa_json_next(&it[2], &val)) <= 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (spa_streq(key, "start")) {
|
|
|
|
|
uint8_t addr[6];
|
|
|
|
|
if (avb_utils_parse_addr(val, len, addr) >= 0 &&
|
|
|
|
|
memcmp(addr, maap_base, 4) == 0) {
|
|
|
|
|
offset = addr[4] << 8 | addr[5];
|
|
|
|
|
have_offset = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (spa_streq(key, "count")) {
|
|
|
|
|
spa_json_parse_int(val, len, &count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (count > 0 && have_offset) {
|
|
|
|
|
maap->count = count;
|
|
|
|
|
maap->offset = offset;
|
|
|
|
|
maap->state = STATE_PROBE;
|
|
|
|
|
maap->probe_count = MAAP_PROBE_RETRANSMITS;
|
|
|
|
|
maap->timeout = PROBE_TIMEOUT(0);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int save_state(struct maap *maap)
|
|
|
|
|
{
|
|
|
|
|
char *ptr;
|
|
|
|
|
size_t size;
|
|
|
|
|
FILE *f;
|
|
|
|
|
char key[512];
|
|
|
|
|
uint32_t count;
|
|
|
|
|
|
|
|
|
|
if ((f = open_memstream(&ptr, &size)) == NULL)
|
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
|
|
fprintf(f, "[ ");
|
|
|
|
|
fprintf(f, "{ \"start\": \"%02x:%02x:%02x:%02x:%02x:%02x\", ",
|
|
|
|
|
maap_base[0], maap_base[1], maap_base[2],
|
|
|
|
|
maap_base[3], (maap->offset >> 8) & 0xff,
|
|
|
|
|
maap->offset & 0xff);
|
|
|
|
|
fprintf(f, " \"count\": %u } ", maap->count);
|
|
|
|
|
fprintf(f, "]");
|
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
|
|
count = pw_properties_set(maap->props, "maap.addresses", ptr);
|
|
|
|
|
free(ptr);
|
|
|
|
|
|
|
|
|
|
if (count > 0) {
|
|
|
|
|
snprintf(key, sizeof(key), "maap.%s", maap->server->ifname);
|
|
|
|
|
pw_conf_save_state("module-avb", key, maap->props);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
static void maap_periodic(void *data, uint64_t now)
|
2022-03-15 18:16:00 +01:00
|
|
|
{
|
|
|
|
|
struct maap *maap = data;
|
2022-04-06 12:58:47 +02:00
|
|
|
|
|
|
|
|
if (now < maap->timeout)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
switch(maap->state) {
|
|
|
|
|
case STATE_IDLE:
|
|
|
|
|
break;
|
|
|
|
|
case STATE_PROBE:
|
|
|
|
|
send_packet(maap, now, AVB_MAAP_MESSAGE_TYPE_PROBE, NULL, 0);
|
2022-04-06 15:37:42 +02:00
|
|
|
if (--maap->probe_count == 0) {
|
2022-04-06 12:58:47 +02:00
|
|
|
maap->state = STATE_ANNOUNCE;
|
2022-04-06 15:37:42 +02:00
|
|
|
save_state(maap);
|
|
|
|
|
}
|
2022-04-06 12:58:47 +02:00
|
|
|
maap->timeout = PROBE_TIMEOUT(now);
|
|
|
|
|
break;
|
|
|
|
|
case STATE_ANNOUNCE:
|
|
|
|
|
send_packet(maap, now, AVB_MAAP_MESSAGE_TYPE_ANNOUNCE, NULL, 0);
|
|
|
|
|
maap->timeout = ANNOUNCE_TIMEOUT(now);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void maap_free(struct maap *maap)
|
|
|
|
|
{
|
2022-04-03 12:32:25 +02:00
|
|
|
pw_loop_destroy_source(maap->server->impl->loop, maap->source);
|
2022-03-15 18:16:00 +01:00
|
|
|
spa_hook_remove(&maap->server_listener);
|
2022-04-06 12:58:47 +02:00
|
|
|
pw_properties_free(maap->props);
|
2022-03-15 18:16:00 +01:00
|
|
|
free(maap);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
static void maap_destroy(void *data)
|
|
|
|
|
{
|
|
|
|
|
struct maap *maap = data;
|
|
|
|
|
maap_free(maap);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 18:16:00 +01:00
|
|
|
static const struct server_events server_events = {
|
2022-03-25 10:28:18 +01:00
|
|
|
AVB_VERSION_SERVER_EVENTS,
|
2022-03-15 18:16:00 +01:00
|
|
|
.destroy = maap_destroy,
|
2022-04-06 12:58:47 +02:00
|
|
|
.periodic = maap_periodic,
|
2022-03-15 18:16:00 +01:00
|
|
|
};
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
struct avb_maap *avb_maap_register(struct server *server)
|
2022-03-15 18:16:00 +01:00
|
|
|
{
|
|
|
|
|
struct maap *maap;
|
2022-04-03 12:32:25 +02:00
|
|
|
uint8_t bmac[6] = AVB_MAAP_MAC;
|
2022-04-06 12:58:47 +02:00
|
|
|
int fd, res;
|
2022-04-03 12:32:25 +02:00
|
|
|
|
|
|
|
|
fd = avb_server_make_socket(server, AVB_TSN_ETH, bmac);
|
2022-04-06 12:58:47 +02:00
|
|
|
if (fd < 0) {
|
|
|
|
|
res = fd;
|
|
|
|
|
goto error;
|
|
|
|
|
}
|
2022-03-15 18:16:00 +01:00
|
|
|
|
|
|
|
|
maap = calloc(1, sizeof(*maap));
|
2022-04-03 12:32:25 +02:00
|
|
|
if (maap == NULL) {
|
|
|
|
|
res = -errno;
|
|
|
|
|
goto error_close;
|
|
|
|
|
}
|
2022-04-06 12:58:47 +02:00
|
|
|
maap->props = pw_properties_new(NULL, NULL);
|
|
|
|
|
if (maap->props == NULL) {
|
|
|
|
|
res = -errno;
|
|
|
|
|
goto error_free;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-15 18:16:00 +01:00
|
|
|
maap->server = server;
|
2022-07-18 15:39:06 +02:00
|
|
|
pw_log_info("0x%"PRIx64" %d", server->entity_id, server->ifindex);
|
2022-03-15 18:16:00 +01:00
|
|
|
|
2023-02-22 15:21:24 +01:00
|
|
|
pw_random(maap->xsubi, sizeof(maap->xsubi));
|
|
|
|
|
|
2022-04-06 15:37:42 +02:00
|
|
|
load_state(maap);
|
2022-04-03 12:32:25 +02:00
|
|
|
|
|
|
|
|
maap->source = pw_loop_add_io(server->impl->loop, fd, SPA_IO_IN, true, on_socket_data, maap);
|
|
|
|
|
if (maap->source == NULL) {
|
|
|
|
|
res = -errno;
|
|
|
|
|
pw_log_error("maap %p: can't create maap source: %m", maap);
|
2022-04-06 12:58:47 +02:00
|
|
|
goto error_free;
|
2022-04-03 12:32:25 +02:00
|
|
|
}
|
2022-03-15 18:16:00 +01:00
|
|
|
avdecc_server_add_listener(server, &maap->server_listener, &server_events, maap);
|
|
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
return (struct avb_maap *)maap;
|
2022-04-03 12:32:25 +02:00
|
|
|
|
2022-04-06 12:58:47 +02:00
|
|
|
error_free:
|
2022-04-03 12:32:25 +02:00
|
|
|
free(maap);
|
|
|
|
|
error_close:
|
|
|
|
|
close(fd);
|
2022-04-06 12:58:47 +02:00
|
|
|
error:
|
|
|
|
|
errno = -res;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int avb_maap_reserve(struct avb_maap *m, uint32_t count)
|
|
|
|
|
{
|
|
|
|
|
struct maap *maap = (struct maap*)m;
|
2022-04-06 15:37:42 +02:00
|
|
|
if (count > maap->count)
|
|
|
|
|
make_new_address(maap, 0, count);
|
2022-04-06 12:58:47 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int avb_maap_get_address(struct avb_maap *m, uint8_t addr[6], uint32_t index)
|
|
|
|
|
{
|
|
|
|
|
struct maap *maap = (struct maap*)m;
|
|
|
|
|
uint16_t offset;
|
|
|
|
|
|
|
|
|
|
if (maap->state != STATE_ANNOUNCE)
|
|
|
|
|
return -EAGAIN;
|
|
|
|
|
|
|
|
|
|
memcpy(addr, maap_base, 6);
|
|
|
|
|
offset = maap->offset + index;
|
|
|
|
|
addr[4] = offset >> 8;
|
|
|
|
|
addr[5] = offset;
|
|
|
|
|
return 0;
|
2022-03-15 18:16:00 +01:00
|
|
|
}
|