mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
avb: implement more MRP
Join a READY listener MRP attribute when we recveive the transmit response. Also listen for talker attributes. Remove attribute callbacks, we don't need them because we moved the packet construction in the MRP users. Implement notify for listener attributes. A connect will now make my MOTU send samples to PipeWire.
This commit is contained in:
parent
f64f8cdd4d
commit
0868f0c7b0
11 changed files with 325 additions and 204 deletions
|
|
@ -28,6 +28,7 @@
|
|||
#include <pipewire/pipewire.h>
|
||||
|
||||
#include "acmp.h"
|
||||
#include "msrp.h"
|
||||
#include "internal.h"
|
||||
|
||||
static const uint8_t mac[6] = AVB_BROADCAST_MAC;
|
||||
|
|
@ -52,6 +53,9 @@ struct acmp {
|
|||
#define PENDING_CONTROLLER 2
|
||||
struct spa_list pending[3];
|
||||
uint16_t sequence_id[3];
|
||||
|
||||
struct avbtp_msrp_attribute *listener_attr;
|
||||
struct avbtp_msrp_attribute *talker_attr;
|
||||
};
|
||||
|
||||
static void *pending_new(struct acmp *acmp, uint32_t type, uint64_t now, uint32_t timeout_ms,
|
||||
|
|
@ -161,6 +165,14 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
|
|||
reply->sequence_id = htons(pending->old_sequence_id);
|
||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_CONNECT_RX_RESPONSE);
|
||||
|
||||
acmp->listener_attr->attr.listener.stream_id = reply->stream_id;
|
||||
acmp->listener_attr->param = AVBTP_MSRP_LISTENER_PARAM_READY;
|
||||
avbtp_mrp_mad_begin(server->mrp, now, acmp->listener_attr->mrp);
|
||||
avbtp_mrp_mad_join(server->mrp, now, acmp->listener_attr->mrp, true);
|
||||
|
||||
acmp->talker_attr->attr.talker.stream_id = reply->stream_id;
|
||||
avbtp_mrp_mad_begin(server->mrp, now, acmp->talker_attr->mrp);
|
||||
|
||||
res = avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, pending->size);
|
||||
|
||||
|
|
@ -210,6 +222,8 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
|
|||
reply->sequence_id = htons(pending->old_sequence_id);
|
||||
AVBTP_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVBTP_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
|
||||
|
||||
avbtp_mrp_mad_leave(server->mrp, now, acmp->listener_attr->mrp);
|
||||
|
||||
res = avbtp_server_send_packet(server, reply->hdr.eth.dest,
|
||||
AVB_TSN_ETH, reply, pending->size);
|
||||
|
||||
|
|
@ -409,6 +423,11 @@ struct avbtp_acmp *avbtp_acmp_register(struct server *server)
|
|||
spa_list_init(&acmp->pending[PENDING_LISTENER]);
|
||||
spa_list_init(&acmp->pending[PENDING_CONTROLLER]);
|
||||
|
||||
acmp->listener_attr = avbtp_msrp_attribute_new(server->msrp,
|
||||
AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
||||
acmp->talker_attr = avbtp_msrp_attribute_new(server->msrp,
|
||||
AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE);
|
||||
|
||||
avdecc_server_add_listener(server, &acmp->server_listener, &server_events, acmp);
|
||||
|
||||
return (struct avbtp_acmp*)acmp;
|
||||
|
|
|
|||
|
|
@ -232,11 +232,16 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
|
|||
AVBTP_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 = 2;
|
||||
server->domain_attr->attr.domain.sr_class_vid = htons(2);
|
||||
|
||||
avbtp_mrp_mad_begin(server->mrp, 0, server->domain_attr->mrp);
|
||||
avbtp_mrp_mad_join(server->mrp, 0, server->domain_attr->mrp, true);
|
||||
|
||||
server->listener_attr = avbtp_msrp_attribute_new(server->msrp,
|
||||
AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER);
|
||||
server->listener_attr->attr.listener.stream_id = htobe64(0);
|
||||
avbtp_mrp_mad_begin(server->mrp, 0, server->listener_attr->mrp);
|
||||
|
||||
return server;
|
||||
|
||||
error_free:
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ struct server {
|
|||
struct avbtp_msrp *msrp;
|
||||
|
||||
struct avbtp_msrp_attribute *domain_attr;
|
||||
struct avbtp_msrp_attribute *listener_attr;
|
||||
};
|
||||
|
||||
static inline const struct descriptor *server_find_descriptor(struct server *server,
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ static const uint8_t mac[6] = AVB_MMRP_MAC;
|
|||
struct attr {
|
||||
struct avbtp_mmrp_attribute attr;
|
||||
struct spa_list link;
|
||||
struct avbtp_mrp_attribute *a;
|
||||
uint8_t addr[6];
|
||||
};
|
||||
|
||||
struct mmrp {
|
||||
|
|
@ -43,15 +41,6 @@ struct mmrp {
|
|||
struct spa_list attributes;
|
||||
};
|
||||
|
||||
static struct attr *find_attr_by_addr(struct mmrp *mmrp, const uint8_t addr[6])
|
||||
{
|
||||
struct attr *a;
|
||||
spa_list_for_each(a, &mmrp->attributes, link)
|
||||
if (memcmp(a->addr, addr, 6) == 0)
|
||||
return a;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool mmrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||
{
|
||||
const struct avbtp_packet_mmrp_msg *msg = hdr;
|
||||
|
|
@ -69,42 +58,53 @@ static int mmrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
|
|||
{
|
||||
struct mmrp *mmrp = data;
|
||||
struct attr *a;
|
||||
pw_log_info("leave all");
|
||||
spa_list_for_each(a, &mmrp->attributes, link)
|
||||
if (a->attr.type == attribute_type)
|
||||
avbtp_mrp_update_state(mmrp->server->mrp, now, a->a, event);
|
||||
avbtp_mrp_update_state(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_service_requirement(const struct avbtp_packet_mmrp_service_requirement *t)
|
||||
{
|
||||
char buf[128];
|
||||
pw_log_info("service requirement");
|
||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||
}
|
||||
|
||||
static int process_service_requirement(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_mmrp_service_requirement *t = m;
|
||||
char buf[128];
|
||||
struct attr *a;
|
||||
|
||||
pw_log_info("service requirement");
|
||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||
debug_service_requirement(t);
|
||||
|
||||
a = find_attr_by_addr(mmrp, t->addr);
|
||||
if (a)
|
||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->a, event);
|
||||
spa_list_for_each(a, &mmrp->attributes, link)
|
||||
if (a->attr.type == attr_type &&
|
||||
memcmp(a->attr.attr.service_requirement.addr, t->addr, 6) == 0)
|
||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_process_mac(const struct avbtp_packet_mmrp_mac *t)
|
||||
{
|
||||
char buf[128];
|
||||
pw_log_info("mac");
|
||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||
}
|
||||
|
||||
static int process_mac(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_mmrp_mac *t = m;
|
||||
char buf[128];
|
||||
struct attr *a;
|
||||
|
||||
pw_log_info("mac");
|
||||
pw_log_info(" %s", avbtp_utils_format_addr(buf, sizeof(buf), t->addr));
|
||||
debug_process_mac(t);
|
||||
|
||||
a = find_attr_by_addr(mmrp, t->addr);
|
||||
if (a)
|
||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->a, event);
|
||||
spa_list_for_each(a, &mmrp->attributes, link)
|
||||
if (a->attr.type == attr_type &&
|
||||
memcmp(a->attr.attr.mac.addr, t->addr, 6) == 0)
|
||||
avbtp_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ static int mmrp_message(void *data, uint64_t now, const void *message, int len)
|
|||
if (memcmp(p->eth.dest, mac, 6) != 0)
|
||||
return 0;
|
||||
|
||||
pw_log_info("MMRP");
|
||||
pw_log_debug("MMRP");
|
||||
return avbtp_mrp_parse_packet(mmrp->server->mrp,
|
||||
now, message, len, &info, mmrp);
|
||||
}
|
||||
|
|
@ -159,22 +159,6 @@ static const struct server_events server_events = {
|
|||
.message = mmrp_message
|
||||
};
|
||||
|
||||
static int mmrp_attr_compare(void *data, struct avbtp_mrp_attribute *a, struct avbtp_mrp_attribute *b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmrp_attr_merge(void *data, struct avbtp_mrp_attribute *a, int vector)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct avbtp_mrp_attribute_callbacks attr_cb = {
|
||||
AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS,
|
||||
.compare = mmrp_attr_compare,
|
||||
.merge = mmrp_attr_merge
|
||||
};
|
||||
|
||||
struct avbtp_mmrp_attribute *avbtp_mmrp_attribute_new(struct avbtp_mmrp *m,
|
||||
uint8_t type)
|
||||
{
|
||||
|
|
@ -182,13 +166,11 @@ struct avbtp_mmrp_attribute *avbtp_mmrp_attribute_new(struct avbtp_mmrp *m,
|
|||
struct avbtp_mrp_attribute *attr;
|
||||
struct attr *a;
|
||||
|
||||
attr = avbtp_mrp_attribute_new(mmrp->server->mrp,
|
||||
&attr_cb, mmrp, sizeof(struct attr));
|
||||
attr = avbtp_mrp_attribute_new(mmrp->server->mrp, sizeof(struct attr));
|
||||
|
||||
a = attr->user_data;
|
||||
a->a = attr;
|
||||
a->attr.mrp = attr;
|
||||
a->attr.type = type;
|
||||
|
||||
spa_list_append(&mmrp->attributes, &a->link);
|
||||
|
||||
return &a->attr;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ struct avbtp_packet_mmrp_mac {
|
|||
struct avbtp_mmrp;
|
||||
|
||||
struct avbtp_mmrp_attribute {
|
||||
struct avbtp_mrp_attribute *mrp;
|
||||
uint8_t type;
|
||||
union {
|
||||
struct avbtp_packet_mmrp_service_requirement service_requirement;
|
||||
|
|
|
|||
|
|
@ -32,16 +32,15 @@
|
|||
#define MRP_PERIODTIMER_MS 1000
|
||||
|
||||
#define mrp_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct avbtp_mrp_events, m, v, ##__VA_ARGS__)
|
||||
#define mrp_emit_tx_event(s,e,st) mrp_emit(s, tx_event, 0, e, st)
|
||||
#define mrp_emit_event(s,n,e) mrp_emit(s,event,0,n,e)
|
||||
#define mrp_emit_notify(s,n,a,e) mrp_emit(s,notify,0,n,a,e)
|
||||
|
||||
struct attribute {
|
||||
struct avbtp_mrp_attribute attr;
|
||||
struct spa_list link;
|
||||
uint8_t applicant_state;
|
||||
uint8_t registrar_state;
|
||||
uint16_t pending_indications;
|
||||
uint64_t leave_timeout;
|
||||
struct spa_callbacks cb;
|
||||
};
|
||||
|
||||
struct mrp {
|
||||
|
|
@ -69,6 +68,7 @@ static void global_event(struct mrp *mrp, uint64_t now, uint8_t event)
|
|||
struct attribute *a;
|
||||
spa_list_for_each(a, &mrp->attributes, link)
|
||||
avbtp_mrp_update_state((struct avbtp_mrp*)mrp, now, &a->attr, event);
|
||||
mrp_emit_event(mrp, now, event);
|
||||
}
|
||||
|
||||
static void mrp_periodic(void *data, uint64_t now)
|
||||
|
|
@ -78,37 +78,37 @@ static void mrp_periodic(void *data, uint64_t now)
|
|||
struct attribute *a;
|
||||
|
||||
if (now > mrp->periodic_timeout) {
|
||||
mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||
|
||||
if (mrp->periodic_timeout > 0)
|
||||
global_event(mrp, now, AVBTP_MRP_EVENT_PERIODIC);
|
||||
mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||
}
|
||||
if (now > mrp->leave_all_timeout) {
|
||||
mrp->leave_all_timeout = now + MRP_LVATIMER_MS * SPA_NSEC_PER_MSEC;
|
||||
|
||||
if (mrp->leave_all_timeout > 0) {
|
||||
global_event(mrp, now, AVBTP_MRP_EVENT_RX_LVA);
|
||||
leave_all = true;
|
||||
}
|
||||
mrp->leave_all_timeout = now + (MRP_LVATIMER_MS + (random() % (MRP_LVATIMER_MS / 2)))
|
||||
* SPA_NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
if (now > mrp->join_timeout) {
|
||||
if (mrp->join_timeout > 0) {
|
||||
uint8_t event = leave_all ? AVBTP_MRP_EVENT_TX_LVA : AVBTP_MRP_EVENT_TX;
|
||||
|
||||
mrp->join_timeout = now + MRP_JOINTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||
|
||||
mrp_emit_tx_event(mrp, event, true);
|
||||
|
||||
global_event(mrp, now, event);
|
||||
|
||||
mrp_emit_tx_event(mrp, event, false);
|
||||
}
|
||||
mrp->join_timeout = now + MRP_JOINTIMER_MS * SPA_NSEC_PER_MSEC;
|
||||
}
|
||||
|
||||
spa_list_for_each(a, &mrp->attributes, link) {
|
||||
if (now > a->leave_timeout) {
|
||||
if (a->leave_timeout > 0 && now > a->leave_timeout) {
|
||||
a->leave_timeout = 0;
|
||||
avbtp_mrp_update_state((struct avbtp_mrp*)mrp, now, &a->attr, AVBTP_MRP_EVENT_LV_TIMER);
|
||||
}
|
||||
if (a->attr.pending_notify) {
|
||||
mrp_emit_notify(mrp, now, &a->attr, a->attr.pending_notify);
|
||||
a->attr.pending_notify = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static const struct server_events server_events = {
|
||||
|
|
@ -125,8 +125,8 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
|||
|
||||
while (m < e && (m[0] != 0 || m[1] != 0)) {
|
||||
const struct avbtp_packet_mrp_hdr *hdr = (const struct avbtp_packet_mrp_hdr*)m;
|
||||
uint8_t attr_len = hdr->attribute_length;
|
||||
uint8_t attr_type = hdr->attribute_type;
|
||||
uint8_t attr_len = hdr->attribute_length;
|
||||
size_t hdr_size;
|
||||
bool has_param;
|
||||
|
||||
|
|
@ -141,11 +141,11 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
|||
uint16_t i, num_values = AVBTP_MRP_VECTOR_GET_NUM_VALUES(v);
|
||||
uint8_t event_len = (num_values+2)/3;
|
||||
uint8_t param_len = has_param ? (num_values+3)/4 : 0;
|
||||
int len = sizeof(*v) + attr_len + event_len + param_len;
|
||||
int plen = sizeof(*v) + attr_len + event_len + param_len;
|
||||
const uint8_t *first = v->first_value;
|
||||
uint8_t event[3], param[4] = { 0, };
|
||||
|
||||
if (m + len > e)
|
||||
if (m + plen > e)
|
||||
return -EPROTO;
|
||||
|
||||
if (v->lva)
|
||||
|
|
@ -168,14 +168,14 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
|||
info->process(data, now, attr_type, first,
|
||||
event[i%3], param[i%4], i);
|
||||
}
|
||||
m += len;
|
||||
m += plen;
|
||||
}
|
||||
m += 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *m,
|
||||
const struct avbtp_mrp_attribute_callbacks *cb, void *data,
|
||||
size_t user_size)
|
||||
{
|
||||
struct mrp *mrp = (struct mrp*)m;
|
||||
|
|
@ -186,16 +186,14 @@ struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *m,
|
|||
return NULL;
|
||||
|
||||
a->attr.user_data = SPA_PTROFF(a, sizeof(*a), void);
|
||||
a->cb = SPA_CALLBACKS_INIT(cb, data);
|
||||
spa_list_append(&mrp->attributes, &a->link);
|
||||
|
||||
return &a->attr;
|
||||
}
|
||||
|
||||
static uint8_t get_tx_event(struct avbtp_mrp *mrp, struct attribute *a,
|
||||
int event, bool leave_all)
|
||||
static uint8_t get_pending_send(struct avbtp_mrp *mrp, struct attribute *a, bool leave_all)
|
||||
{
|
||||
uint8_t ev = 0;
|
||||
uint8_t send = 0;
|
||||
|
||||
switch (a->applicant_state) {
|
||||
case AVBTP_MRP_VP:
|
||||
|
|
@ -206,59 +204,51 @@ static uint8_t get_tx_event(struct avbtp_mrp *mrp, struct attribute *a,
|
|||
if (leave_all && a->applicant_state == AVBTP_MRP_VP) {
|
||||
switch (a->registrar_state) {
|
||||
case AVBTP_MRP_IN:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_IN;
|
||||
send = AVBTP_MRP_SEND_IN;
|
||||
break;
|
||||
default:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_MT;
|
||||
send = AVBTP_MRP_SEND_MT;
|
||||
break;
|
||||
}
|
||||
} else if (leave_all || a->applicant_state != AVBTP_MRP_QP) {
|
||||
switch (a->registrar_state) {
|
||||
case AVBTP_MRP_IN:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_JOININ;
|
||||
send = AVBTP_MRP_SEND_JOININ;
|
||||
break;
|
||||
default:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_JOINMT;
|
||||
send = AVBTP_MRP_SEND_JOINMT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVBTP_MRP_VN:
|
||||
case AVBTP_MRP_AN:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_NEW;
|
||||
send = AVBTP_MRP_SEND_NEW;
|
||||
break;
|
||||
case AVBTP_MRP_LA:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_LV;
|
||||
send = AVBTP_MRP_SEND_LV;
|
||||
break;
|
||||
case AVBTP_MRP_LO:
|
||||
switch (a->registrar_state) {
|
||||
case AVBTP_MRP_IN:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_IN;
|
||||
send = AVBTP_MRP_SEND_IN;
|
||||
break;
|
||||
default:
|
||||
ev = AVBTP_MRP_ATTRIBUTE_EVENT_MT;
|
||||
send = AVBTP_MRP_SEND_MT;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ev;
|
||||
}
|
||||
|
||||
static int do_tx(struct avbtp_mrp *mrp, struct attribute *a,
|
||||
int event, bool leave_all)
|
||||
{
|
||||
uint8_t ev = get_tx_event(mrp, a, event, leave_all);
|
||||
|
||||
spa_callbacks_call(&a->cb, struct avbtp_mrp_attribute_callbacks,
|
||||
merge, 0, &a->attr, ev);
|
||||
|
||||
return 0;
|
||||
return send;
|
||||
}
|
||||
|
||||
void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
||||
struct avbtp_mrp_attribute *attr, int event)
|
||||
{
|
||||
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
|
||||
uint8_t notify = 0;
|
||||
uint8_t send = 0;
|
||||
|
||||
switch (event) {
|
||||
case AVBTP_MRP_EVENT_BEGIN:
|
||||
a->registrar_state = AVBTP_MRP_MT;
|
||||
|
|
@ -267,14 +257,14 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|||
if (a->registrar_state == AVBTP_MRP_LV)
|
||||
a->leave_timeout = 0;
|
||||
a->registrar_state = AVBTP_MRP_IN;
|
||||
a->pending_indications |= AVBTP_PENDING_JOIN_NEW;
|
||||
notify = AVBTP_MRP_NOTIFY_JOIN_NEW;
|
||||
break;
|
||||
case AVBTP_MRP_EVENT_RX_JOININ:
|
||||
case AVBTP_MRP_EVENT_RX_JOINMT:
|
||||
if (a->registrar_state == AVBTP_MRP_LV)
|
||||
a->leave_timeout = 0;
|
||||
if (a->registrar_state == AVBTP_MRP_MT) {
|
||||
a->pending_indications |= AVBTP_PENDING_JOIN;
|
||||
notify = AVBTP_MRP_NOTIFY_JOIN;
|
||||
}
|
||||
a->registrar_state = AVBTP_MRP_IN;
|
||||
break;
|
||||
|
|
@ -290,13 +280,14 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|||
case AVBTP_MRP_EVENT_LV_TIMER:
|
||||
case AVBTP_MRP_EVENT_FLUSH:
|
||||
if (a->registrar_state == AVBTP_MRP_LV) {
|
||||
a->pending_indications |= AVBTP_PENDING_LEAVE;
|
||||
notify = AVBTP_MRP_NOTIFY_LEAVE;
|
||||
}
|
||||
a->registrar_state = AVBTP_MRP_MT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
a->attr.pending_notify |= notify;
|
||||
|
||||
switch (event) {
|
||||
case AVBTP_MRP_EVENT_BEGIN:
|
||||
|
|
@ -423,7 +414,7 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|||
case AVBTP_MRP_LA:
|
||||
case AVBTP_MRP_AP:
|
||||
case AVBTP_MRP_LO:
|
||||
do_tx(mrp, a, event, false);
|
||||
send = get_pending_send(mrp, a, false);
|
||||
break;
|
||||
}
|
||||
switch (a->applicant_state) {
|
||||
|
|
@ -455,7 +446,7 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|||
case AVBTP_MRP_QA:
|
||||
case AVBTP_MRP_AP:
|
||||
case AVBTP_MRP_QP:
|
||||
do_tx(mrp, a, event, true);
|
||||
send = get_pending_send(mrp, a, true);
|
||||
}
|
||||
switch (a->applicant_state) {
|
||||
case AVBTP_MRP_VO:
|
||||
|
|
@ -479,6 +470,7 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
a->attr.pending_send = send;
|
||||
}
|
||||
|
||||
void avbtp_mrp_rx_event(struct avbtp_mrp *mrp, uint64_t now,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "packets.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define AVBTP_MRP_PROTOCOL_VERSION 0
|
||||
|
||||
struct avbtp_packet_mrp {
|
||||
struct avbtp_ethernet_header eth;
|
||||
uint8_t version;
|
||||
|
|
@ -50,7 +52,7 @@ struct avbtp_packet_mrp_vector {
|
|||
uint8_t first_value[0];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define AVBTP_MRP_VECTOR_SET_NUM_VALUES(a,v) ((a)->nv1 = ((v) >> 8),(p)->nv2 = (v))
|
||||
#define AVBTP_MRP_VECTOR_SET_NUM_VALUES(a,v) ((a)->nv1 = ((v) >> 8),(a)->nv2 = (v))
|
||||
#define AVBTP_MRP_VECTOR_GET_NUM_VALUES(a) ((a)->nv1 << 8 | (a)->nv2)
|
||||
|
||||
struct avbtp_packet_mrp_footer {
|
||||
|
|
@ -105,33 +107,23 @@ struct avbtp_packet_mrp_footer {
|
|||
#define AVBTP_MRP_ATTRIBUTE_EVENT_MT 4
|
||||
#define AVBTP_MRP_ATTRIBUTE_EVENT_LV 5
|
||||
|
||||
#define AVBTP_PENDING_JOIN_NEW (1u<<0)
|
||||
#define AVBTP_PENDING_JOIN (1u<<1)
|
||||
#define AVBTP_PENDING_LEAVE (1u<<2)
|
||||
#define AVBTP_MRP_SEND_NEW 1
|
||||
#define AVBTP_MRP_SEND_JOININ 2
|
||||
#define AVBTP_MRP_SEND_IN 3
|
||||
#define AVBTP_MRP_SEND_JOINMT 4
|
||||
#define AVBTP_MRP_SEND_MT 5
|
||||
#define AVBTP_MRP_SEND_LV 6
|
||||
|
||||
struct avbtp_mrp_events {
|
||||
#define AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
int (*tx_event) (void *data, uint8_t event, bool start);
|
||||
};
|
||||
#define AVBTP_MRP_NOTIFY_JOIN_NEW (1u<<0)
|
||||
#define AVBTP_MRP_NOTIFY_JOIN (1u<<1)
|
||||
#define AVBTP_MRP_NOTIFY_LEAVE (1u<<2)
|
||||
|
||||
struct avbtp_mrp_attribute {
|
||||
uint16_t domain;
|
||||
uint8_t type;
|
||||
uint8_t pending_send;
|
||||
uint8_t pending_notify;
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
struct avbtp_mrp_attribute_callbacks {
|
||||
#define AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
int (*compare) (void *data, struct avbtp_mrp_attribute *a, struct avbtp_mrp_attribute *b);
|
||||
|
||||
int (*merge) (void *data, struct avbtp_mrp_attribute *a, int vector);
|
||||
};
|
||||
|
||||
|
||||
struct avbtp_mrp_parse_info {
|
||||
#define AVBTP_VERSION_MRP_PARSE_INFO 0
|
||||
uint32_t version;
|
||||
|
|
@ -149,7 +141,6 @@ int avbtp_mrp_parse_packet(struct avbtp_mrp *mrp, uint64_t now, const void *pkt,
|
|||
const struct avbtp_mrp_parse_info *cb, void *data);
|
||||
|
||||
struct avbtp_mrp_attribute *avbtp_mrp_attribute_new(struct avbtp_mrp *mrp,
|
||||
const struct avbtp_mrp_attribute_callbacks *cb, void *data,
|
||||
size_t user_size);
|
||||
|
||||
void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
|
||||
|
|
@ -162,6 +153,15 @@ void avbtp_mrp_mad_begin(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_a
|
|||
void avbtp_mrp_mad_join(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr, bool is_new);
|
||||
void avbtp_mrp_mad_leave(struct avbtp_mrp *mrp, uint64_t now, struct avbtp_mrp_attribute *attr);
|
||||
|
||||
struct avbtp_mrp_events {
|
||||
#define AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
void (*event) (void *data, uint64_t now, uint8_t event);
|
||||
|
||||
void (*notify) (void *data, uint64_t now, struct avbtp_mrp_attribute *attr, uint8_t notify);
|
||||
};
|
||||
|
||||
struct avbtp_mrp *avbtp_mrp_new(struct server *server);
|
||||
void avbtp_mrp_destroy(struct avbtp_mrp *mrp);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,16 +44,7 @@ struct msrp {
|
|||
struct spa_list attributes;
|
||||
};
|
||||
|
||||
static struct attr *find_attr_by_stream_id(struct msrp *msrp, uint64_t stream_id)
|
||||
{
|
||||
struct attr *a;
|
||||
spa_list_for_each(a, &msrp->attributes, link)
|
||||
if (a->attr.attr.talker.stream_id == stream_id)
|
||||
return a;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void debug_msrp_talker(const struct avbtp_packet_msrp_talker *t)
|
||||
static void debug_msrp_talker_common(const struct avbtp_packet_msrp_talker *t)
|
||||
{
|
||||
char buf[128];
|
||||
pw_log_info(" stream-id: %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(t->stream_id)));
|
||||
|
|
@ -66,25 +57,37 @@ static void debug_msrp_talker(const struct avbtp_packet_msrp_talker *t)
|
|||
pw_log_info(" accumulated-latency: %d", ntohl(t->accumulated_latency));
|
||||
}
|
||||
|
||||
static void debug_msrp_talker(const struct avbtp_packet_msrp_talker *t)
|
||||
{
|
||||
pw_log_info("talker");
|
||||
debug_msrp_talker_common(t);
|
||||
}
|
||||
|
||||
static void notify_talker(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
||||
{
|
||||
pw_log_info("> notify talker: %d", notify);
|
||||
debug_msrp_talker(&attr->attr.attr.talker);
|
||||
}
|
||||
|
||||
static int process_talker(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_msrp_talker *t = m;
|
||||
struct attr *a;
|
||||
|
||||
pw_log_info("talker");
|
||||
debug_msrp_talker(t);
|
||||
|
||||
a = find_attr_by_stream_id(msrp, be64toh(t->stream_id));
|
||||
if (a)
|
||||
spa_list_for_each(a, &msrp->attributes, link)
|
||||
if (a->attr.type == attr_type &&
|
||||
a->attr.attr.talker.stream_id == t->stream_id) {
|
||||
a->attr.attr.talker = *t;
|
||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_msrp_talker_fail(const struct avbtp_packet_msrp_talker_fail *t)
|
||||
{
|
||||
char buf[128];
|
||||
debug_msrp_talker(&t->talker);
|
||||
pw_log_info("talker fail");
|
||||
debug_msrp_talker_common(&t->talker);
|
||||
pw_log_info(" bridge-id: %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(t->bridge_id)));
|
||||
pw_log_info(" failure-code: %d", t->failure_code);
|
||||
}
|
||||
|
|
@ -93,50 +96,137 @@ static int process_talker_fail(struct msrp *msrp, uint64_t now, uint8_t attr_typ
|
|||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_msrp_talker_fail *t = m;
|
||||
pw_log_info("talker fail");
|
||||
struct attr *a;
|
||||
|
||||
debug_msrp_talker_fail(t);
|
||||
|
||||
spa_list_for_each(a, &msrp->attributes, link)
|
||||
if (a->attr.type == attr_type &&
|
||||
a->attr.attr.talker_fail.talker.stream_id == t->talker.stream_id)
|
||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_msrp_listener(const struct avbtp_packet_msrp_listener *l)
|
||||
{
|
||||
char buf[128];
|
||||
pw_log_info(" %s", avbtp_utils_format_id(buf, sizeof(buf), l->stream_id));
|
||||
pw_log_info("listener");
|
||||
pw_log_info(" %s", avbtp_utils_format_id(buf, sizeof(buf), be64toh(l->stream_id)));
|
||||
}
|
||||
|
||||
static void notify_listener(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
||||
{
|
||||
pw_log_info("> notify listener: %d", notify);
|
||||
debug_msrp_listener(&attr->attr.attr.listener);
|
||||
}
|
||||
|
||||
static int process_listener(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_msrp_listener *l = m;
|
||||
pw_log_info("listener");
|
||||
debug_msrp_listener(l);
|
||||
struct attr *a;
|
||||
spa_list_for_each(a, &msrp->attributes, link)
|
||||
if (a->attr.type == attr_type &&
|
||||
a->attr.attr.listener.stream_id == l->stream_id)
|
||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
|
||||
{
|
||||
struct avbtp_packet_msrp_msg *msg = m;
|
||||
struct avbtp_packet_mrp_vector *v;
|
||||
struct avbtp_packet_msrp_listener *l;
|
||||
struct avbtp_packet_mrp_footer *f;
|
||||
uint8_t *ev;
|
||||
size_t attr_list_length = sizeof(*v) + sizeof(*l) + sizeof(*f) + 1 + 1;
|
||||
|
||||
msg->attribute_type = AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER;
|
||||
msg->attribute_length = sizeof(*l);
|
||||
msg->attribute_list_length = htons(attr_list_length);
|
||||
|
||||
v = (struct avbtp_packet_mrp_vector *)msg->attribute_list;
|
||||
v->lva = 0;
|
||||
AVBTP_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
||||
|
||||
l = (struct avbtp_packet_msrp_listener *)v->first_value;
|
||||
*l = a->attr.attr.listener;
|
||||
|
||||
ev = SPA_PTROFF(l, sizeof(*l), uint8_t);
|
||||
*ev = a->attr.mrp->pending_send * 6 * 6;
|
||||
|
||||
ev = SPA_PTROFF(ev, sizeof(*ev), uint8_t);
|
||||
*ev = a->attr.param * 4 * 4 * 4;
|
||||
|
||||
f = SPA_PTROFF(ev, sizeof(*ev), struct avbtp_packet_mrp_footer);
|
||||
f->end_mark = 0;
|
||||
|
||||
return attr_list_length + sizeof(*msg);
|
||||
}
|
||||
|
||||
|
||||
static void debug_msrp_domain(const struct avbtp_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));
|
||||
}
|
||||
|
||||
static void notify_domain(struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify)
|
||||
{
|
||||
pw_log_info("> notify domain: %d", notify);
|
||||
debug_msrp_domain(&attr->attr.attr.domain);
|
||||
}
|
||||
|
||||
static int process_domain(struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_msrp_domain *d = m;
|
||||
pw_log_info("domain");
|
||||
debug_msrp_domain(d);
|
||||
struct attr *a;
|
||||
spa_list_for_each(a, &msrp->attributes, link)
|
||||
if (a->attr.type == attr_type)
|
||||
avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int encode_domain(struct msrp *msrp, struct attr *a, void *m)
|
||||
{
|
||||
struct avbtp_packet_msrp_msg *msg = m;
|
||||
struct avbtp_packet_mrp_vector *v;
|
||||
struct avbtp_packet_msrp_domain *d;
|
||||
struct avbtp_packet_mrp_footer *f;
|
||||
uint8_t *ev;
|
||||
size_t attr_list_length = sizeof(*v) + sizeof(*d) + sizeof(*f) + 1;
|
||||
|
||||
msg->attribute_type = AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN;
|
||||
msg->attribute_length = sizeof(*d);
|
||||
msg->attribute_list_length = htons(attr_list_length);
|
||||
|
||||
v = (struct avbtp_packet_mrp_vector *)msg->attribute_list;
|
||||
v->lva = 0;
|
||||
AVBTP_MRP_VECTOR_SET_NUM_VALUES(v, 1);
|
||||
|
||||
d = (struct avbtp_packet_msrp_domain *)v->first_value;
|
||||
*d = a->attr.attr.domain;
|
||||
|
||||
ev = SPA_PTROFF(d, sizeof(*d), uint8_t);
|
||||
*ev = a->attr.mrp->pending_send * 36;
|
||||
|
||||
f = SPA_PTROFF(ev, sizeof(*ev), struct avbtp_packet_mrp_footer);
|
||||
f->end_mark = 0;
|
||||
|
||||
return attr_list_length + sizeof(*msg);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int (*dispatch) (struct msrp *msrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num);
|
||||
int (*encode) (struct msrp *msrp, struct attr *attr, void *m);
|
||||
void (*notify) (struct msrp *msrp, uint64_t now, struct attr *attr, uint8_t notify);
|
||||
} dispatch[] = {
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { process_talker, },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { process_talker_fail, },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER] = { process_listener, },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { process_domain, },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { process_talker, NULL, notify_talker, },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { process_talker_fail, NULL, NULL },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_LISTENER] = { process_listener, encode_listener, notify_listener },
|
||||
[AVBTP_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { process_domain, encode_domain, notify_domain, },
|
||||
};
|
||||
|
||||
static bool msrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||
|
|
@ -188,7 +278,7 @@ static int msrp_message(void *data, uint64_t now, const void *message, int len)
|
|||
if (memcmp(p->eth.dest, mac, 6) != 0)
|
||||
return 0;
|
||||
|
||||
pw_log_info("MSRP");
|
||||
pw_log_debug("MSRP");
|
||||
return avbtp_mrp_parse_packet(msrp->server->mrp,
|
||||
now, message, len, &info, msrp);
|
||||
}
|
||||
|
|
@ -206,23 +296,6 @@ static const struct server_events server_events = {
|
|||
.message = msrp_message
|
||||
};
|
||||
|
||||
static int msrp_attr_compare(void *data, struct avbtp_mrp_attribute *a, struct avbtp_mrp_attribute *b)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msrp_attr_merge(void *data, struct avbtp_mrp_attribute *a, int vector)
|
||||
{
|
||||
pw_log_info("attr merge");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct avbtp_mrp_attribute_callbacks attr_cb = {
|
||||
AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS,
|
||||
.compare = msrp_attr_compare,
|
||||
.merge = msrp_attr_merge
|
||||
};
|
||||
|
||||
struct avbtp_msrp_attribute *avbtp_msrp_attribute_new(struct avbtp_msrp *m,
|
||||
uint8_t type)
|
||||
{
|
||||
|
|
@ -230,26 +303,63 @@ struct avbtp_msrp_attribute *avbtp_msrp_attribute_new(struct avbtp_msrp *m,
|
|||
struct avbtp_mrp_attribute *attr;
|
||||
struct attr *a;
|
||||
|
||||
attr = avbtp_mrp_attribute_new(msrp->server->mrp,
|
||||
&attr_cb, msrp, sizeof(struct attr));
|
||||
attr = avbtp_mrp_attribute_new(msrp->server->mrp, sizeof(struct attr));
|
||||
|
||||
a = attr->user_data;
|
||||
a->attr.mrp = attr;
|
||||
spa_list_append(&msrp->attributes, &a->link);
|
||||
a->attr.type = type;
|
||||
spa_list_append(&msrp->attributes, &a->link);
|
||||
|
||||
return &a->attr;
|
||||
}
|
||||
|
||||
static int msrp_tx_event(void *data, uint8_t event, bool start)
|
||||
static void msrp_event(void *data, uint64_t now, uint8_t event)
|
||||
{
|
||||
pw_log_info("tx %s", start ? "start" : "stop");
|
||||
return 0;
|
||||
struct msrp *msrp = data;
|
||||
uint8_t buffer[2048];
|
||||
struct avbtp_packet_mrp *p = (struct avbtp_packet_mrp*)buffer;
|
||||
struct avbtp_packet_mrp_footer *f;
|
||||
void *msg = SPA_PTROFF(buffer, sizeof(*p), void);
|
||||
struct attr *a;
|
||||
int len, count = 0;
|
||||
size_t total = sizeof(*p) + 2;
|
||||
|
||||
p->version = AVBTP_MRP_PROTOCOL_VERSION;
|
||||
|
||||
spa_list_for_each(a, &msrp->attributes, link) {
|
||||
if (!a->attr.mrp->pending_send)
|
||||
continue;
|
||||
if (dispatch[a->attr.type].encode == NULL)
|
||||
continue;
|
||||
|
||||
len = dispatch[a->attr.type].encode(msrp, a, msg);
|
||||
if (len < 0)
|
||||
break;
|
||||
|
||||
count++;
|
||||
msg = SPA_PTROFF(msg, len, void);
|
||||
total += len;
|
||||
}
|
||||
f = (struct avbtp_packet_mrp_footer *)msg;
|
||||
f->end_mark = 0;
|
||||
|
||||
if (count > 0)
|
||||
avbtp_server_send_packet(msrp->server, mac, AVB_MSRP_ETH,
|
||||
buffer, total);
|
||||
}
|
||||
|
||||
static void msrp_notify(void *data, uint64_t now, struct avbtp_mrp_attribute *attr, uint8_t notify)
|
||||
{
|
||||
struct msrp *msrp = data;
|
||||
struct attr *a = attr->user_data;
|
||||
if (dispatch[a->attr.type].notify != NULL)
|
||||
dispatch[a->attr.type].notify(msrp, now, a, notify);
|
||||
}
|
||||
|
||||
static const struct avbtp_mrp_events mrp_events = {
|
||||
AVBTP_VERSION_MRP_ATTRIBUTE_CALLBACKS,
|
||||
.tx_event = msrp_tx_event
|
||||
.event = msrp_event,
|
||||
.notify = msrp_notify
|
||||
};
|
||||
|
||||
struct avbtp_msrp *avbtp_msrp_register(struct server *server)
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ struct avbtp_packet_msrp_domain {
|
|||
uint16_t sr_class_vid;
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define AVBTP_MSRP_LISTENER_PARAM_IGNORE 0
|
||||
#define AVBTP_MSRP_LISTENER_PARAM_ASKING_FAILED 1
|
||||
#define AVBTP_MSRP_LISTENER_PARAM_READY 2
|
||||
#define AVBTP_MSRP_LISTENER_PARAM_READY_FAILED 3
|
||||
|
||||
struct avbtp_msrp_attribute {
|
||||
struct avbtp_mrp_attribute *mrp;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@ static const uint8_t mac[6] = AVB_MVRP_MAC;
|
|||
struct attr {
|
||||
struct avbtp_mvrp_attribute attr;
|
||||
struct spa_list link;
|
||||
struct avbtp_mrp_attribute *a;
|
||||
uint16_t vlan;
|
||||
};
|
||||
|
||||
struct mvrp {
|
||||
|
|
@ -42,15 +40,6 @@ struct mvrp {
|
|||
struct spa_list attributes;
|
||||
};
|
||||
|
||||
static struct attr *find_attr_by_vlan(struct mvrp *mvrp, uint16_t vlan)
|
||||
{
|
||||
struct attr *a;
|
||||
spa_list_for_each(a, &mvrp->attributes, link)
|
||||
if (a->vlan == vlan)
|
||||
return a;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool mvrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
|
||||
{
|
||||
const struct avbtp_packet_mvrp_msg *msg = hdr;
|
||||
|
|
@ -68,34 +57,31 @@ static int mvrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
|
|||
{
|
||||
struct mvrp *mvrp = data;
|
||||
struct attr *a;
|
||||
pw_log_info("leave all");
|
||||
spa_list_for_each(a, &mvrp->attributes, link)
|
||||
if (a->attr.type == attribute_type)
|
||||
avbtp_mrp_update_state(mvrp->server->mrp, now, a->a, event);
|
||||
avbtp_mrp_update_state(mvrp->server->mrp, now, a->attr.mrp, event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void debug_vid(const void *p)
|
||||
{
|
||||
const struct avbtp_packet_mvrp_vid *t = p;
|
||||
pw_log_info("vid");
|
||||
pw_log_info(" %d", ntohs(t->vlan));
|
||||
}
|
||||
|
||||
static int process_vid(struct mvrp *mvrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num)
|
||||
{
|
||||
const struct avbtp_packet_mvrp_vid *t = m;
|
||||
struct attr *a;
|
||||
uint16_t vlan = ntohs(t->vlan);
|
||||
|
||||
pw_log_info("vid");
|
||||
pw_log_info(" %d", vlan);
|
||||
|
||||
a = find_attr_by_vlan(mvrp, vlan);
|
||||
if (a)
|
||||
avbtp_mrp_rx_event(mvrp->server->mrp, now, a->a, event);
|
||||
return 0;
|
||||
return mvrp_attr_event(mvrp, now, attr_type, event);
|
||||
}
|
||||
|
||||
static const struct {
|
||||
void (*debug) (const void *p);
|
||||
int (*dispatch) (struct mvrp *mvrp, uint64_t now, uint8_t attr_type,
|
||||
const void *m, uint8_t event, uint8_t param, int num);
|
||||
} dispatch[] = {
|
||||
[AVBTP_MVRP_ATTRIBUTE_TYPE_VID] = { process_vid, },
|
||||
[AVBTP_MVRP_ATTRIBUTE_TYPE_VID] = { debug_vid, process_vid, },
|
||||
};
|
||||
|
||||
static int mvrp_process(void *data, uint64_t now, uint8_t attribute_type, const void *value,
|
||||
|
|
@ -123,7 +109,7 @@ static int mvrp_message(void *data, uint64_t now, const void *message, int len)
|
|||
if (memcmp(p->eth.dest, mac, 6) != 0)
|
||||
return 0;
|
||||
|
||||
pw_log_info("MVRP");
|
||||
pw_log_debug("MVRP");
|
||||
return avbtp_mrp_parse_packet(mvrp->server->mrp,
|
||||
now, message, len, &info, mvrp);
|
||||
}
|
||||
|
|
@ -141,6 +127,23 @@ static const struct server_events server_events = {
|
|||
.message = mvrp_message
|
||||
};
|
||||
|
||||
struct avbtp_mvrp_attribute *avbtp_mvrp_attribute_new(struct avbtp_mvrp *m,
|
||||
uint8_t type)
|
||||
{
|
||||
struct mvrp *mvrp = (struct mvrp*)m;
|
||||
struct avbtp_mrp_attribute *attr;
|
||||
struct attr *a;
|
||||
|
||||
attr = avbtp_mrp_attribute_new(mvrp->server->mrp, sizeof(struct attr));
|
||||
|
||||
a = attr->user_data;
|
||||
a->attr.mrp = attr;
|
||||
a->attr.type = type;
|
||||
spa_list_append(&mvrp->attributes, &a->link);
|
||||
|
||||
return &a->attr;
|
||||
}
|
||||
|
||||
struct avbtp_mvrp *avbtp_mvrp_register(struct server *server)
|
||||
{
|
||||
struct mvrp *mvrp;
|
||||
|
|
|
|||
|
|
@ -47,12 +47,16 @@ struct avbtp_packet_mvrp_vid {
|
|||
struct avbtp_mvrp;
|
||||
|
||||
struct avbtp_mvrp_attribute {
|
||||
struct avbtp_mrp_attribute *mrp;
|
||||
uint8_t type;
|
||||
union {
|
||||
struct avbtp_packet_mvrp_vid vid;
|
||||
} attr;
|
||||
};
|
||||
|
||||
struct avbtp_mvrp_attribute *avbtp_mvrp_attribute_new(struct avbtp_mvrp *mvrp,
|
||||
uint8_t type);
|
||||
|
||||
struct avbtp_mvrp *avbtp_mvrp_register(struct server *server);
|
||||
|
||||
#endif /* AVBTP_MVRP_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue