diff --git a/src/modules/module-avbtp/acmp.c b/src/modules/module-avbtp/acmp.c index 6cfe74d49..e8c8f4c96 100644 --- a/src/modules/module-avbtp/acmp.c +++ b/src/modules/module-avbtp/acmp.c @@ -28,6 +28,7 @@ #include #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; diff --git a/src/modules/module-avbtp/avdecc.c b/src/modules/module-avbtp/avdecc.c index f82ef2488..b667bd8ac 100644 --- a/src/modules/module-avbtp/avdecc.c +++ b/src/modules/module-avbtp/avdecc.c @@ -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: diff --git a/src/modules/module-avbtp/internal.h b/src/modules/module-avbtp/internal.h index fed353ade..fc22491bf 100644 --- a/src/modules/module-avbtp/internal.h +++ b/src/modules/module-avbtp/internal.h @@ -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, diff --git a/src/modules/module-avbtp/mmrp.c b/src/modules/module-avbtp/mmrp.c index 3943dacf8..440312dc3 100644 --- a/src/modules/module-avbtp/mmrp.c +++ b/src/modules/module-avbtp/mmrp.c @@ -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; diff --git a/src/modules/module-avbtp/mmrp.h b/src/modules/module-avbtp/mmrp.h index f74e12a01..1ed6beb9f 100644 --- a/src/modules/module-avbtp/mmrp.h +++ b/src/modules/module-avbtp/mmrp.h @@ -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; diff --git a/src/modules/module-avbtp/mrp.c b/src/modules/module-avbtp/mrp.c index 5384a5bef..c3d4ac8e8 100644 --- a/src/modules/module-avbtp/mrp.c +++ b/src/modules/module-avbtp/mrp.c @@ -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) { + if (mrp->periodic_timeout > 0) + global_event(mrp, now, AVBTP_MRP_EVENT_PERIODIC); mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC; - - global_event(mrp, now, AVBTP_MRP_EVENT_PERIODIC); } if (now > mrp->leave_all_timeout) { - mrp->leave_all_timeout = now + MRP_LVATIMER_MS * SPA_NSEC_PER_MSEC; - - global_event(mrp, now, AVBTP_MRP_EVENT_RX_LVA); - leave_all = true; + 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) { - uint8_t event = leave_all ? AVBTP_MRP_EVENT_TX_LVA : AVBTP_MRP_EVENT_TX; - + if (mrp->join_timeout > 0) { + uint8_t event = leave_all ? AVBTP_MRP_EVENT_TX_LVA : AVBTP_MRP_EVENT_TX; + global_event(mrp, now, event); + } 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); } 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, diff --git a/src/modules/module-avbtp/mrp.h b/src/modules/module-avbtp/mrp.h index 4d0ea8a83..d10f3546c 100644 --- a/src/modules/module-avbtp/mrp.h +++ b/src/modules/module-avbtp/mrp.h @@ -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); diff --git a/src/modules/module-avbtp/msrp.c b/src/modules/module-avbtp/msrp.c index d838df347..d9b891a12 100644 --- a/src/modules/module-avbtp/msrp.c +++ b/src/modules/module-avbtp/msrp.c @@ -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) - avbtp_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event); + 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) diff --git a/src/modules/module-avbtp/msrp.h b/src/modules/module-avbtp/msrp.h index 83a28cbfd..02f30798d 100644 --- a/src/modules/module-avbtp/msrp.h +++ b/src/modules/module-avbtp/msrp.h @@ -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; diff --git a/src/modules/module-avbtp/mvrp.c b/src/modules/module-avbtp/mvrp.c index 66012d28c..bc60fee8d 100644 --- a/src/modules/module-avbtp/mvrp.c +++ b/src/modules/module-avbtp/mvrp.c @@ -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; diff --git a/src/modules/module-avbtp/mvrp.h b/src/modules/module-avbtp/mvrp.h index 76bceef4a..2595ca986 100644 --- a/src/modules/module-avbtp/mvrp.h +++ b/src/modules/module-avbtp/mvrp.h @@ -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 */