avb: improve MRP state handling

This commit is contained in:
Wim Taymans 2022-03-25 09:16:50 +01:00
parent 0868f0c7b0
commit d5b4c12684

View file

@ -246,167 +246,207 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
struct avbtp_mrp_attribute *attr, int event) struct avbtp_mrp_attribute *attr, int event)
{ {
struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr); struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
uint8_t notify = 0; uint8_t notify = 0, state;
uint8_t send = 0; uint8_t send = 0;
state = a->registrar_state;
switch (event) { switch (event) {
case AVBTP_MRP_EVENT_BEGIN: case AVBTP_MRP_EVENT_BEGIN:
a->registrar_state = AVBTP_MRP_MT; state = AVBTP_MRP_MT;
break; break;
case AVBTP_MRP_EVENT_RX_NEW: case AVBTP_MRP_EVENT_RX_NEW:
if (a->registrar_state == AVBTP_MRP_LV)
a->leave_timeout = 0;
a->registrar_state = AVBTP_MRP_IN;
notify = AVBTP_MRP_NOTIFY_JOIN_NEW; notify = AVBTP_MRP_NOTIFY_JOIN_NEW;
switch (state) {
case AVBTP_MRP_LV:
a->leave_timeout = 0;
SPA_FALLTHROUGH;
case AVBTP_MRP_MT:
case AVBTP_MRP_IN:
state = AVBTP_MRP_IN;
break;
}
break; break;
case AVBTP_MRP_EVENT_RX_JOININ: case AVBTP_MRP_EVENT_RX_JOININ:
case AVBTP_MRP_EVENT_RX_JOINMT: case AVBTP_MRP_EVENT_RX_JOINMT:
if (a->registrar_state == AVBTP_MRP_LV) switch (state) {
case AVBTP_MRP_LV:
a->leave_timeout = 0; a->leave_timeout = 0;
if (a->registrar_state == AVBTP_MRP_MT) { SPA_FALLTHROUGH;
case AVBTP_MRP_MT:
notify = AVBTP_MRP_NOTIFY_JOIN; notify = AVBTP_MRP_NOTIFY_JOIN;
SPA_FALLTHROUGH;
case AVBTP_MRP_IN:
state = AVBTP_MRP_IN;
break;
} }
a->registrar_state = AVBTP_MRP_IN;
break; break;
case AVBTP_MRP_EVENT_RX_LV: case AVBTP_MRP_EVENT_RX_LV:
notify = AVBTP_MRP_NOTIFY_LEAVE;
SPA_FALLTHROUGH;
case AVBTP_MRP_EVENT_RX_LVA: case AVBTP_MRP_EVENT_RX_LVA:
case AVBTP_MRP_EVENT_TX_LVA: case AVBTP_MRP_EVENT_TX_LVA:
case AVBTP_MRP_EVENT_REDECLARE: case AVBTP_MRP_EVENT_REDECLARE:
if (a->registrar_state == AVBTP_MRP_IN) { switch (state) {
case AVBTP_MRP_IN:
a->leave_timeout = now + MRP_LVTIMER_MS * SPA_NSEC_PER_MSEC; a->leave_timeout = now + MRP_LVTIMER_MS * SPA_NSEC_PER_MSEC;
a->registrar_state = AVBTP_MRP_LV; state = AVBTP_MRP_LV;
break;
} }
break; break;
case AVBTP_MRP_EVENT_LV_TIMER: case AVBTP_MRP_EVENT_LV_TIMER:
case AVBTP_MRP_EVENT_FLUSH: switch (state) {
if (a->registrar_state == AVBTP_MRP_LV) { case AVBTP_MRP_LV:
notify = AVBTP_MRP_NOTIFY_LEAVE; notify = AVBTP_MRP_NOTIFY_LEAVE;
break;
}
break;
case AVBTP_MRP_EVENT_FLUSH:
notify = AVBTP_MRP_NOTIFY_LEAVE;
switch (state) {
case AVBTP_MRP_LV:
case AVBTP_MRP_MT:
case AVBTP_MRP_IN:
state = AVBTP_MRP_MT;
break;
} }
a->registrar_state = AVBTP_MRP_MT;
break; break;
default: default:
break; break;
} }
a->attr.pending_notify |= notify; a->attr.pending_notify |= notify;
if (a->registrar_state != state || notify) {
pw_log_info("attr %p: %d %d -> %d %d", a, event, a->registrar_state, state, notify);
a->registrar_state = state;
}
state = a->applicant_state;
switch (event) { switch (event) {
case AVBTP_MRP_EVENT_BEGIN: case AVBTP_MRP_EVENT_BEGIN:
a->applicant_state = AVBTP_MRP_VO; state = AVBTP_MRP_VO;
break; break;
case AVBTP_MRP_EVENT_NEW: case AVBTP_MRP_EVENT_NEW:
a->applicant_state = AVBTP_MRP_VN; switch (state) {
case AVBTP_MRP_VN:
case AVBTP_MRP_AN:
break;
default:
state = AVBTP_MRP_VN;
break;
}
break; break;
case AVBTP_MRP_EVENT_JOIN: case AVBTP_MRP_EVENT_JOIN:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VO: case AVBTP_MRP_VO:
case AVBTP_MRP_LO: case AVBTP_MRP_LO:
a->applicant_state = AVBTP_MRP_VP; state = AVBTP_MRP_VP;
break; break;
case AVBTP_MRP_LA: case AVBTP_MRP_LA:
a->applicant_state = AVBTP_MRP_AA; state = AVBTP_MRP_AA;
break; break;
case AVBTP_MRP_AO: case AVBTP_MRP_AO:
a->applicant_state = AVBTP_MRP_AP; state = AVBTP_MRP_AP;
break; break;
case AVBTP_MRP_QO: case AVBTP_MRP_QO:
a->applicant_state = AVBTP_MRP_QP; state = AVBTP_MRP_QP;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_LV: case AVBTP_MRP_EVENT_LV:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
a->applicant_state = AVBTP_MRP_QO; state = AVBTP_MRP_QO;
break; break;
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
a->applicant_state = AVBTP_MRP_AO; state = AVBTP_MRP_AO;
break; break;
case AVBTP_MRP_VP: case AVBTP_MRP_VP:
a->applicant_state = AVBTP_MRP_VO; state = AVBTP_MRP_VO;
break; break;
case AVBTP_MRP_VN: case AVBTP_MRP_VN:
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
case AVBTP_MRP_QA: case AVBTP_MRP_QA:
a->applicant_state = AVBTP_MRP_LA; state = AVBTP_MRP_LA;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_RX_JOININ: case AVBTP_MRP_EVENT_RX_JOININ:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VO: case AVBTP_MRP_VO:
a->applicant_state = AVBTP_MRP_AO; state = AVBTP_MRP_AO;
break; break;
case AVBTP_MRP_VP: case AVBTP_MRP_VP:
a->applicant_state = AVBTP_MRP_AP; state = AVBTP_MRP_AP;
break; break;
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
a->applicant_state = AVBTP_MRP_QA; state = AVBTP_MRP_QA;
break; break;
case AVBTP_MRP_AO: case AVBTP_MRP_AO:
a->applicant_state = AVBTP_MRP_QO; state = AVBTP_MRP_QO;
break; break;
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
a->applicant_state = AVBTP_MRP_QP; state = AVBTP_MRP_QP;
break; break;
} }
SPA_FALLTHROUGH; SPA_FALLTHROUGH;
case AVBTP_MRP_EVENT_RX_IN: case AVBTP_MRP_EVENT_RX_IN:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
a->applicant_state = AVBTP_MRP_QA; state = AVBTP_MRP_QA;
break; break;
} }
SPA_FALLTHROUGH; SPA_FALLTHROUGH;
case AVBTP_MRP_EVENT_RX_JOINMT: case AVBTP_MRP_EVENT_RX_JOINMT:
case AVBTP_MRP_EVENT_RX_MT: case AVBTP_MRP_EVENT_RX_MT:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_QA: case AVBTP_MRP_QA:
a->applicant_state = AVBTP_MRP_AA; state = AVBTP_MRP_AA;
break; break;
case AVBTP_MRP_QO: case AVBTP_MRP_QO:
a->applicant_state = AVBTP_MRP_AO; state = AVBTP_MRP_AO;
break; break;
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
a->applicant_state = AVBTP_MRP_AP; state = AVBTP_MRP_AP;
break; break;
case AVBTP_MRP_LO: case AVBTP_MRP_LO:
a->applicant_state = AVBTP_MRP_VO; state = AVBTP_MRP_VO;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_RX_LV: case AVBTP_MRP_EVENT_RX_LV:
case AVBTP_MRP_EVENT_RX_LVA: case AVBTP_MRP_EVENT_RX_LVA:
case AVBTP_MRP_EVENT_REDECLARE: case AVBTP_MRP_EVENT_REDECLARE:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VO: case AVBTP_MRP_VO:
case AVBTP_MRP_AO: case AVBTP_MRP_AO:
case AVBTP_MRP_QO: case AVBTP_MRP_QO:
a->applicant_state = AVBTP_MRP_LO; state = AVBTP_MRP_LO;
break; break;
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
a->applicant_state = AVBTP_MRP_VN; state = AVBTP_MRP_VN;
break; break;
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
case AVBTP_MRP_QA: case AVBTP_MRP_QA:
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
a->applicant_state = AVBTP_MRP_VP; state = AVBTP_MRP_VP;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_PERIODIC: case AVBTP_MRP_EVENT_PERIODIC:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_QA: case AVBTP_MRP_QA:
a->applicant_state = AVBTP_MRP_AA; state = AVBTP_MRP_AA;
break; break;
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
a->applicant_state = AVBTP_MRP_AP; state = AVBTP_MRP_AP;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_TX: case AVBTP_MRP_EVENT_TX:
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VP: case AVBTP_MRP_VP:
case AVBTP_MRP_VN: case AVBTP_MRP_VN:
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
@ -415,29 +455,28 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
case AVBTP_MRP_LO: case AVBTP_MRP_LO:
send = get_pending_send(mrp, a, false); send = get_pending_send(mrp, a, false);
break;
} }
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VP: case AVBTP_MRP_VP:
a->applicant_state = AVBTP_MRP_AA; state = AVBTP_MRP_AA;
break; break;
case AVBTP_MRP_VN: case AVBTP_MRP_VN:
a->applicant_state = AVBTP_MRP_AN; state = AVBTP_MRP_AN;
break; break;
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
a->applicant_state = AVBTP_MRP_QA; state = AVBTP_MRP_QA;
break; break;
case AVBTP_MRP_LA: case AVBTP_MRP_LA:
case AVBTP_MRP_LO: case AVBTP_MRP_LO:
a->applicant_state = AVBTP_MRP_VO; state = AVBTP_MRP_VO;
break; break;
} }
break; break;
case AVBTP_MRP_EVENT_TX_LVA: case AVBTP_MRP_EVENT_TX_LVA:
{ {
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VP: case AVBTP_MRP_VP:
case AVBTP_MRP_VN: case AVBTP_MRP_VN:
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
@ -448,21 +487,21 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
send = get_pending_send(mrp, a, true); send = get_pending_send(mrp, a, true);
} }
switch (a->applicant_state) { switch (state) {
case AVBTP_MRP_VO: case AVBTP_MRP_VO:
case AVBTP_MRP_LA: case AVBTP_MRP_LA:
case AVBTP_MRP_AO: case AVBTP_MRP_AO:
case AVBTP_MRP_QO: case AVBTP_MRP_QO:
a->applicant_state = AVBTP_MRP_LO; state = AVBTP_MRP_LO;
break; break;
case AVBTP_MRP_VN: case AVBTP_MRP_VN:
a->applicant_state = AVBTP_MRP_AN; state = AVBTP_MRP_AN;
break; break;
case AVBTP_MRP_AN: case AVBTP_MRP_AN:
case AVBTP_MRP_AA: case AVBTP_MRP_AA:
case AVBTP_MRP_AP: case AVBTP_MRP_AP:
case AVBTP_MRP_QP: case AVBTP_MRP_QP:
a->applicant_state = AVBTP_MRP_QA; state = AVBTP_MRP_QA;
break; break;
} }
break; break;
@ -470,6 +509,10 @@ void avbtp_mrp_update_state(struct avbtp_mrp *mrp, uint64_t now,
default: default:
break; break;
} }
if (a->applicant_state != state || send) {
pw_log_info("attr %p: %d %d -> %d %d", a, event, a->applicant_state, state, send);
a->applicant_state = state;
}
a->attr.pending_send = send; a->attr.pending_send = send;
} }