mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	avb: improve state machine
Emit per attribute callbacks. Notify events immediately.
This commit is contained in:
		
							parent
							
								
									773bd610aa
								
							
						
					
					
						commit
						9a26df3478
					
				
					 7 changed files with 151 additions and 148 deletions
				
			
		| 
						 | 
				
			
			@ -167,11 +167,11 @@ static int handle_connect_tx_response(struct acmp *acmp, uint64_t now, const voi
 | 
			
		|||
 | 
			
		||||
	acmp->listener_attr->attr.listener.stream_id = reply->stream_id;
 | 
			
		||||
	acmp->listener_attr->param = AVB_MSRP_LISTENER_PARAM_READY;
 | 
			
		||||
	avb_mrp_mad_begin(server->mrp, now, acmp->listener_attr->mrp);
 | 
			
		||||
	avb_mrp_mad_join(server->mrp, now, acmp->listener_attr->mrp, true);
 | 
			
		||||
	avb_mrp_attribute_begin(acmp->listener_attr->mrp, now);
 | 
			
		||||
	avb_mrp_attribute_join(acmp->listener_attr->mrp, now, true);
 | 
			
		||||
 | 
			
		||||
	acmp->talker_attr->attr.talker.stream_id = reply->stream_id;
 | 
			
		||||
	avb_mrp_mad_begin(server->mrp, now, acmp->talker_attr->mrp);
 | 
			
		||||
	avb_mrp_attribute_begin(acmp->talker_attr->mrp, now);
 | 
			
		||||
 | 
			
		||||
	res = avb_server_send_packet(server, reply->hdr.eth.dest,
 | 
			
		||||
			AVB_TSN_ETH, reply, pending->size);
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +222,7 @@ static int handle_disconnect_tx_response(struct acmp *acmp, uint64_t now, const
 | 
			
		|||
	reply->sequence_id = htons(pending->old_sequence_id);
 | 
			
		||||
	AVB_PACKET_ACMP_SET_MESSAGE_TYPE(reply, AVB_ACMP_MESSAGE_TYPE_DISCONNECT_RX_RESPONSE);
 | 
			
		||||
 | 
			
		||||
	avb_mrp_mad_leave(server->mrp, now, acmp->listener_attr->mrp);
 | 
			
		||||
	avb_mrp_attribute_leave(acmp->listener_attr->mrp, now);
 | 
			
		||||
 | 
			
		||||
	res = avb_server_send_packet(server, reply->hdr.eth.dest,
 | 
			
		||||
			AVB_TSN_ETH, reply, pending->size);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -234,13 +234,13 @@ struct server *avdecc_server_new(struct impl *impl, const char *ifname, struct s
 | 
			
		|||
	server->domain_attr->attr.domain.sr_class_priority = 3;
 | 
			
		||||
	server->domain_attr->attr.domain.sr_class_vid = htons(2);
 | 
			
		||||
 | 
			
		||||
	avb_mrp_mad_begin(server->mrp, 0, server->domain_attr->mrp);
 | 
			
		||||
	avb_mrp_mad_join(server->mrp, 0, server->domain_attr->mrp, true);
 | 
			
		||||
	avb_mrp_attribute_begin(server->domain_attr->mrp, 0);
 | 
			
		||||
	avb_mrp_attribute_join(server->domain_attr->mrp, 0, true);
 | 
			
		||||
 | 
			
		||||
	server->listener_attr = avb_msrp_attribute_new(server->msrp,
 | 
			
		||||
			AVB_MSRP_ATTRIBUTE_TYPE_LISTENER);
 | 
			
		||||
	server->listener_attr->attr.listener.stream_id = htobe64(0);
 | 
			
		||||
	avb_mrp_mad_begin(server->mrp, 0, server->listener_attr->mrp);
 | 
			
		||||
	avb_mrp_attribute_begin(server->listener_attr->mrp, 0);
 | 
			
		||||
 | 
			
		||||
	return server;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,7 +60,7 @@ static int mmrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
 | 
			
		|||
	struct attr *a;
 | 
			
		||||
	spa_list_for_each(a, &mmrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attribute_type)
 | 
			
		||||
			avb_mrp_update_state(mmrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_update_state(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ static int process_service_requirement(struct mmrp *mmrp, uint64_t now, uint8_t
 | 
			
		|||
	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)
 | 
			
		||||
			avb_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,7 @@ static int process_mac(struct mmrp *mmrp, uint64_t now, uint8_t attr_type,
 | 
			
		|||
	spa_list_for_each(a, &mmrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attr_type &&
 | 
			
		||||
		    memcmp(a->attr.attr.mac.addr, t->addr, 6) == 0)
 | 
			
		||||
			avb_mrp_rx_event(mmrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,12 +35,21 @@
 | 
			
		|||
#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)
 | 
			
		||||
 | 
			
		||||
#define mrp_attribute_emit(a,m,v,...)		spa_hook_list_call(&a->listener_list, struct avb_mrp_attribute_events, m, v, ##__VA_ARGS__)
 | 
			
		||||
#define mrp_attribute_emit_notify(a,n,e)	mrp_attribute_emit(a,notify,0,n,e)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mrp;
 | 
			
		||||
 | 
			
		||||
struct attribute {
 | 
			
		||||
	struct avb_mrp_attribute attr;
 | 
			
		||||
	struct mrp *mrp;
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	uint8_t applicant_state;
 | 
			
		||||
	uint8_t registrar_state;
 | 
			
		||||
	uint64_t leave_timeout;
 | 
			
		||||
	unsigned joined:1;
 | 
			
		||||
	struct spa_hook_list listener_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mrp {
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +76,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)
 | 
			
		||||
		avb_mrp_update_state((struct avb_mrp*)mrp, now, &a->attr, event);
 | 
			
		||||
		avb_mrp_attribute_update_state(&a->attr, now, event);
 | 
			
		||||
	mrp_emit_event(mrp, now, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,11 +111,7 @@ static void mrp_periodic(void *data, uint64_t now)
 | 
			
		|||
	spa_list_for_each(a, &mrp->attributes, link) {
 | 
			
		||||
		if (a->leave_timeout > 0 && now > a->leave_timeout) {
 | 
			
		||||
			a->leave_timeout = 0;
 | 
			
		||||
			avb_mrp_update_state((struct avb_mrp*)mrp, now, &a->attr, AVB_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;
 | 
			
		||||
			avb_mrp_attribute_update_state(&a->attr, now, AVB_MRP_EVENT_LV_TIMER);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -185,67 +190,26 @@ struct avb_mrp_attribute *avb_mrp_attribute_new(struct avb_mrp *m,
 | 
			
		|||
	if (a == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	a->mrp = mrp;
 | 
			
		||||
	a->attr.user_data = SPA_PTROFF(a, sizeof(*a), void);
 | 
			
		||||
	spa_hook_list_init(&a->listener_list);
 | 
			
		||||
	spa_list_append(&mrp->attributes, &a->link);
 | 
			
		||||
 | 
			
		||||
	return &a->attr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t get_pending_send(struct avb_mrp *mrp, struct attribute *a, bool leave_all)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t send = 0;
 | 
			
		||||
 | 
			
		||||
	switch (a->applicant_state) {
 | 
			
		||||
	case AVB_MRP_VP:
 | 
			
		||||
	case AVB_MRP_AA:
 | 
			
		||||
	case AVB_MRP_AP:
 | 
			
		||||
	case AVB_MRP_QA:
 | 
			
		||||
	case AVB_MRP_QP:
 | 
			
		||||
		if (leave_all && a->applicant_state == AVB_MRP_VP) {
 | 
			
		||||
			switch (a->registrar_state) {
 | 
			
		||||
			case AVB_MRP_IN:
 | 
			
		||||
				send = AVB_MRP_SEND_IN;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				send = AVB_MRP_SEND_MT;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (leave_all || a->applicant_state != AVB_MRP_QP) {
 | 
			
		||||
			switch (a->registrar_state) {
 | 
			
		||||
			case AVB_MRP_IN:
 | 
			
		||||
				send = AVB_MRP_SEND_JOININ;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				send = AVB_MRP_SEND_JOINMT;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_VN:
 | 
			
		||||
	case AVB_MRP_AN:
 | 
			
		||||
		send = AVB_MRP_SEND_NEW;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_LA:
 | 
			
		||||
		send = AVB_MRP_SEND_LV;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_LO:
 | 
			
		||||
		switch (a->registrar_state) {
 | 
			
		||||
		case AVB_MRP_IN:
 | 
			
		||||
			send = AVB_MRP_SEND_IN;
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			send = AVB_MRP_SEND_MT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return send;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		||||
		struct avb_mrp_attribute *attr, int event)
 | 
			
		||||
void avb_mrp_attribute_add_listener(struct avb_mrp_attribute *attr, struct spa_hook *listener,
 | 
			
		||||
		const struct avb_mrp_attribute_events *events, void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
 | 
			
		||||
	spa_hook_list_append(&a->listener_list, listener, events, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_attribute_update_state(struct avb_mrp_attribute *attr, uint64_t now,
 | 
			
		||||
		int event)
 | 
			
		||||
{
 | 
			
		||||
	struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
 | 
			
		||||
	struct mrp *mrp = a->mrp;
 | 
			
		||||
	uint8_t notify = 0, state;
 | 
			
		||||
	uint8_t send = 0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -256,34 +220,27 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		state = AVB_MRP_MT;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_NEW:
 | 
			
		||||
		notify = AVB_MRP_NOTIFY_JOIN_NEW;
 | 
			
		||||
		notify = AVB_MRP_NOTIFY_NEW;
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_LV:
 | 
			
		||||
			a->leave_timeout = 0;
 | 
			
		||||
			SPA_FALLTHROUGH;
 | 
			
		||||
		case AVB_MRP_MT:
 | 
			
		||||
		case AVB_MRP_IN:
 | 
			
		||||
			state = AVB_MRP_IN;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		state = AVB_MRP_IN;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_JOININ:
 | 
			
		||||
	case AVB_MRP_EVENT_RX_JOINMT:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_LV:
 | 
			
		||||
			a->leave_timeout = 0;
 | 
			
		||||
			SPA_FALLTHROUGH;
 | 
			
		||||
                        break;
 | 
			
		||||
		case AVB_MRP_MT:
 | 
			
		||||
			notify = AVB_MRP_NOTIFY_JOIN;
 | 
			
		||||
			SPA_FALLTHROUGH;
 | 
			
		||||
		case AVB_MRP_IN:
 | 
			
		||||
			state = AVB_MRP_IN;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		state = AVB_MRP_IN;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_LV:
 | 
			
		||||
		notify = AVB_MRP_NOTIFY_LEAVE;
 | 
			
		||||
		SPA_FALLTHROUGH;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_LVA:
 | 
			
		||||
	case AVB_MRP_EVENT_TX_LVA:
 | 
			
		||||
	case AVB_MRP_EVENT_REDECLARE:
 | 
			
		||||
| 
						 | 
				
			
			@ -294,19 +251,18 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_LV_TIMER:
 | 
			
		||||
	case AVB_MRP_EVENT_FLUSH:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_LV:
 | 
			
		||||
			notify = AVB_MRP_NOTIFY_LEAVE;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		state = AVB_MRP_MT;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_FLUSH:
 | 
			
		||||
		notify = AVB_MRP_NOTIFY_LEAVE;
 | 
			
		||||
	case AVB_MRP_EVENT_LV_TIMER:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_LV:
 | 
			
		||||
		case AVB_MRP_MT:
 | 
			
		||||
		case AVB_MRP_IN:
 | 
			
		||||
			notify = AVB_MRP_NOTIFY_LEAVE;
 | 
			
		||||
			state = AVB_MRP_MT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -314,9 +270,13 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	a->attr.pending_notify |= notify;
 | 
			
		||||
	if (notify) {
 | 
			
		||||
		mrp_attribute_emit_notify(a, now, notify);
 | 
			
		||||
		mrp_emit_notify(mrp, now, &a->attr, notify);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (a->registrar_state != state || notify) {
 | 
			
		||||
		pw_log_info("attr %p: %d %d -> %d %d", a, event, a->registrar_state, state, notify);
 | 
			
		||||
		pw_log_debug("attr %p: %d %d -> %d %d", a, event, a->registrar_state, state, notify);
 | 
			
		||||
		a->registrar_state = state;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -355,12 +315,6 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_LV:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_QP:
 | 
			
		||||
			state = AVB_MRP_QO;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_AP:
 | 
			
		||||
			state = AVB_MRP_AO;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_VP:
 | 
			
		||||
			state = AVB_MRP_VO;
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -370,6 +324,12 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		case AVB_MRP_QA:
 | 
			
		||||
			state = AVB_MRP_LA;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_AP:
 | 
			
		||||
			state = AVB_MRP_AO;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_QP:
 | 
			
		||||
			state = AVB_MRP_QO;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_JOININ:
 | 
			
		||||
| 
						 | 
				
			
			@ -397,7 +357,7 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
			state = AVB_MRP_QA;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		SPA_FALLTHROUGH;
 | 
			
		||||
		break;
 | 
			
		||||
	case AVB_MRP_EVENT_RX_JOINMT:
 | 
			
		||||
	case AVB_MRP_EVENT_RX_MT:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
| 
						 | 
				
			
			@ -448,13 +408,26 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
	case AVB_MRP_EVENT_TX:
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_VP:
 | 
			
		||||
		case AVB_MRP_AA:
 | 
			
		||||
		case AVB_MRP_AP:
 | 
			
		||||
			if (a->registrar_state == AVB_MRP_IN)
 | 
			
		||||
				send = AVB_MRP_SEND_JOININ;
 | 
			
		||||
			else
 | 
			
		||||
				send = AVB_MRP_SEND_JOINMT;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_VN:
 | 
			
		||||
		case AVB_MRP_AN:
 | 
			
		||||
		case AVB_MRP_AA:
 | 
			
		||||
			send = AVB_MRP_SEND_NEW;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_LA:
 | 
			
		||||
		case AVB_MRP_AP:
 | 
			
		||||
			send = AVB_MRP_SEND_LV;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_LO:
 | 
			
		||||
			send = get_pending_send(mrp, a, false);
 | 
			
		||||
			if (a->registrar_state == AVB_MRP_IN)
 | 
			
		||||
				send = AVB_MRP_SEND_IN;
 | 
			
		||||
			else
 | 
			
		||||
				send = AVB_MRP_SEND_MT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_VP:
 | 
			
		||||
| 
						 | 
				
			
			@ -464,6 +437,11 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
			state = AVB_MRP_AN;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_AN:
 | 
			
		||||
			if(a->registrar_state == AVB_MRP_IN)
 | 
			
		||||
				state = AVB_MRP_QA;
 | 
			
		||||
			else
 | 
			
		||||
				state = AVB_MRP_AA;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_AA:
 | 
			
		||||
		case AVB_MRP_AP:
 | 
			
		||||
			state = AVB_MRP_QA;
 | 
			
		||||
| 
						 | 
				
			
			@ -478,14 +456,24 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
	{
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_VP:
 | 
			
		||||
			if (a->registrar_state == AVB_MRP_IN)
 | 
			
		||||
				send = AVB_MRP_SEND_IN;
 | 
			
		||||
			else
 | 
			
		||||
				send = AVB_MRP_SEND_MT;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_VN:
 | 
			
		||||
		case AVB_MRP_AN:
 | 
			
		||||
			send = AVB_MRP_SEND_NEW;
 | 
			
		||||
			break;
 | 
			
		||||
                case AVB_MRP_AA:
 | 
			
		||||
		case AVB_MRP_LA:
 | 
			
		||||
                case AVB_MRP_QA:
 | 
			
		||||
                case AVB_MRP_AP:
 | 
			
		||||
		case AVB_MRP_QP:
 | 
			
		||||
			send = get_pending_send(mrp, a, true);
 | 
			
		||||
			if (a->registrar_state == AVB_MRP_IN)
 | 
			
		||||
				send = AVB_MRP_SEND_JOININ;
 | 
			
		||||
			else
 | 
			
		||||
				send = AVB_MRP_SEND_JOINMT;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		switch (state) {
 | 
			
		||||
		case AVB_MRP_VO:
 | 
			
		||||
| 
						 | 
				
			
			@ -494,6 +482,9 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		case AVB_MRP_QO:
 | 
			
		||||
			state = AVB_MRP_LO;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_VP:
 | 
			
		||||
			state = AVB_MRP_AA;
 | 
			
		||||
			break;
 | 
			
		||||
		case AVB_MRP_VN:
 | 
			
		||||
			state = AVB_MRP_AN;
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -510,14 +501,14 @@ void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	if (a->applicant_state != state || send) {
 | 
			
		||||
		pw_log_info("attr %p: %d %d -> %d %d", a, event, a->applicant_state, state, send);
 | 
			
		||||
		pw_log_debug("attr %p: %d %d -> %d %d", a, event, a->applicant_state, state, send);
 | 
			
		||||
		a->applicant_state = state;
 | 
			
		||||
	}
 | 
			
		||||
	if (a->joined)
 | 
			
		||||
		a->attr.pending_send = send;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_rx_event(struct avb_mrp *mrp, uint64_t now,
 | 
			
		||||
		struct avb_mrp_attribute *attr, uint8_t event)
 | 
			
		||||
void avb_mrp_attribute_rx_event(struct avb_mrp_attribute *attr, uint64_t now, uint8_t event)
 | 
			
		||||
{
 | 
			
		||||
	static const int map[] = {
 | 
			
		||||
		[AVB_MRP_ATTRIBUTE_EVENT_NEW] = AVB_MRP_EVENT_RX_NEW,
 | 
			
		||||
| 
						 | 
				
			
			@ -527,27 +518,29 @@ void avb_mrp_rx_event(struct avb_mrp *mrp, uint64_t now,
 | 
			
		|||
		[AVB_MRP_ATTRIBUTE_EVENT_MT] = AVB_MRP_EVENT_RX_MT,
 | 
			
		||||
		[AVB_MRP_ATTRIBUTE_EVENT_LV] = AVB_MRP_EVENT_RX_LV,
 | 
			
		||||
	};
 | 
			
		||||
	avb_mrp_update_state(mrp, now, attr, map[event]);
 | 
			
		||||
	avb_mrp_attribute_update_state(attr, now, map[event]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_mad_begin(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr)
 | 
			
		||||
void avb_mrp_attribute_begin(struct avb_mrp_attribute *attr, uint64_t now)
 | 
			
		||||
{
 | 
			
		||||
	struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
 | 
			
		||||
	a->leave_timeout = 0;
 | 
			
		||||
	avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_BEGIN);
 | 
			
		||||
	avb_mrp_attribute_update_state(attr, now, AVB_MRP_EVENT_BEGIN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_mad_join(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr, bool is_new)
 | 
			
		||||
void avb_mrp_attribute_join(struct avb_mrp_attribute *attr, uint64_t now, bool is_new)
 | 
			
		||||
{
 | 
			
		||||
	if (is_new)
 | 
			
		||||
		avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_NEW);
 | 
			
		||||
	else
 | 
			
		||||
		avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_JOIN);
 | 
			
		||||
	struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
 | 
			
		||||
	a->joined = true;
 | 
			
		||||
	int event = is_new ? AVB_MRP_EVENT_NEW : AVB_MRP_EVENT_JOIN;
 | 
			
		||||
	avb_mrp_attribute_update_state(attr, now, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_mad_leave(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr)
 | 
			
		||||
void avb_mrp_attribute_leave(struct avb_mrp_attribute *attr, uint64_t now)
 | 
			
		||||
{
 | 
			
		||||
	avb_mrp_update_state(mrp, now, attr, AVB_MRP_EVENT_LV);
 | 
			
		||||
	struct attribute *a = SPA_CONTAINER_OF(attr, struct attribute, attr);
 | 
			
		||||
	avb_mrp_attribute_update_state(attr, now, AVB_MRP_EVENT_LV);
 | 
			
		||||
	a->joined = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void avb_mrp_destroy(struct avb_mrp *mrp)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -114,16 +114,36 @@ struct avb_packet_mrp_footer {
 | 
			
		|||
#define AVB_MRP_SEND_MT			5
 | 
			
		||||
#define AVB_MRP_SEND_LV			6
 | 
			
		||||
 | 
			
		||||
#define AVB_MRP_NOTIFY_JOIN_NEW		(1u<<0)
 | 
			
		||||
#define AVB_MRP_NOTIFY_JOIN		(1u<<1)
 | 
			
		||||
#define AVB_MRP_NOTIFY_LEAVE		(1u<<2)
 | 
			
		||||
#define AVB_MRP_NOTIFY_NEW		0
 | 
			
		||||
#define AVB_MRP_NOTIFY_JOIN		1
 | 
			
		||||
#define AVB_MRP_NOTIFY_LEAVE		2
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_attribute {
 | 
			
		||||
	uint8_t pending_send;
 | 
			
		||||
	uint8_t pending_notify;
 | 
			
		||||
	void *user_data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_attribute_events {
 | 
			
		||||
#define AVB_VERSION_MRP_ATTRIBUTE_EVENTS	0
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
 | 
			
		||||
	void (*notify) (void *data, uint64_t now, uint8_t notify);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_attribute *avb_mrp_attribute_new(struct avb_mrp *mrp,
 | 
			
		||||
		size_t user_size);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_attribute_update_state(struct avb_mrp_attribute *attr, uint64_t now, int event);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_attribute_rx_event(struct avb_mrp_attribute *attr, uint64_t now, uint8_t event);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_attribute_begin(struct avb_mrp_attribute *attr, uint64_t now);
 | 
			
		||||
void avb_mrp_attribute_join(struct avb_mrp_attribute *attr, uint64_t now, bool is_new);
 | 
			
		||||
void avb_mrp_attribute_leave(struct avb_mrp_attribute *attr, uint64_t now);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_attribute_add_listener(struct avb_mrp_attribute *attr, struct spa_hook *listener,
 | 
			
		||||
		const struct avb_mrp_attribute_events *events, void *data);
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_parse_info {
 | 
			
		||||
#define AVB_VERSION_MRP_PARSE_INFO	0
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
| 
						 | 
				
			
			@ -136,25 +156,11 @@ struct avb_mrp_parse_info {
 | 
			
		|||
			uint8_t event, uint8_t param, int index);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int avb_mrp_parse_packet(struct avb_mrp *mrp, uint64_t now, const void *pkt, int size,
 | 
			
		||||
		const struct avb_mrp_parse_info *cb, void *data);
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_attribute *avb_mrp_attribute_new(struct avb_mrp *mrp,
 | 
			
		||||
		size_t user_size);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_update_state(struct avb_mrp *mrp, uint64_t now,
 | 
			
		||||
		struct avb_mrp_attribute *attr, int event);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_rx_event(struct avb_mrp *mrp, uint64_t now,
 | 
			
		||||
		struct avb_mrp_attribute *attr, uint8_t event);
 | 
			
		||||
 | 
			
		||||
void avb_mrp_mad_begin(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr);
 | 
			
		||||
void avb_mrp_mad_join(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr, bool is_new);
 | 
			
		||||
void avb_mrp_mad_leave(struct avb_mrp *mrp, uint64_t now, struct avb_mrp_attribute *attr);
 | 
			
		||||
 | 
			
		||||
struct avb_mrp_events {
 | 
			
		||||
#define AVB_VERSION_MRP_ATTRIBUTE_CALLBACKS	0
 | 
			
		||||
#define AVB_VERSION_MRP_EVENTS	0
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
 | 
			
		||||
	void (*event) (void *data, uint64_t now, uint8_t event);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -78,7 +78,7 @@ static int process_talker(struct msrp *msrp, uint64_t now, uint8_t attr_type,
 | 
			
		|||
		if (a->attr.type == attr_type &&
 | 
			
		||||
		    a->attr.attr.talker.stream_id == t->stream_id) {
 | 
			
		||||
			a->attr.attr.talker = *t;
 | 
			
		||||
			avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
		}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ static int process_talker_fail(struct msrp *msrp, uint64_t now, uint8_t attr_typ
 | 
			
		|||
	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)
 | 
			
		||||
			avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ static int process_listener(struct msrp *msrp, uint64_t now, uint8_t attr_type,
 | 
			
		|||
	spa_list_for_each(a, &msrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attr_type &&
 | 
			
		||||
		    a->attr.attr.listener.stream_id == l->stream_id)
 | 
			
		||||
			avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
static int encode_listener(struct msrp *msrp, struct attr *a, void *m)
 | 
			
		||||
| 
						 | 
				
			
			@ -184,7 +184,7 @@ static int process_domain(struct msrp *msrp, uint64_t now, uint8_t attr_type,
 | 
			
		|||
	struct attr *a;
 | 
			
		||||
	spa_list_for_each(a, &msrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attr_type)
 | 
			
		||||
			avb_mrp_rx_event(msrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -218,15 +218,16 @@ static int encode_domain(struct msrp *msrp, struct attr *a, void *m)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
	const char *name;
 | 
			
		||||
	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[] = {
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { process_talker, NULL, notify_talker, },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { process_talker_fail, NULL, NULL },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_LISTENER] = { process_listener, encode_listener, notify_listener },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { process_domain, encode_domain, notify_domain, },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_ADVERTISE] = { "talker", process_talker, NULL, notify_talker, },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_TALKER_FAILED] = { "talker-fail", process_talker_fail, NULL, NULL },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_LISTENER] = { "listener", process_listener, encode_listener, notify_listener },
 | 
			
		||||
	[AVB_MSRP_ATTRIBUTE_TYPE_DOMAIN] = { "domain", process_domain, encode_domain, notify_domain, },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static bool msrp_check_header(void *data, const void *hdr, size_t *hdr_size, bool *has_params)
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +249,7 @@ static int msrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
 | 
			
		|||
	struct attr *a;
 | 
			
		||||
	spa_list_for_each(a, &msrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attribute_type)
 | 
			
		||||
			avb_mrp_update_state(msrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_update_state(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -332,6 +333,9 @@ static void msrp_event(void *data, uint64_t now, uint8_t event)
 | 
			
		|||
		if (dispatch[a->attr.type].encode == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		pw_log_debug("send %s %d", dispatch[a->attr.type].name,
 | 
			
		||||
				a->attr.mrp->pending_send);
 | 
			
		||||
 | 
			
		||||
		len = dispatch[a->attr.type].encode(msrp, a, msg);
 | 
			
		||||
		if (len < 0)
 | 
			
		||||
			break;
 | 
			
		||||
| 
						 | 
				
			
			@ -357,7 +361,7 @@ static void msrp_notify(void *data, uint64_t now, struct avb_mrp_attribute *attr
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const struct avb_mrp_events mrp_events = {
 | 
			
		||||
	AVB_VERSION_MRP_ATTRIBUTE_CALLBACKS,
 | 
			
		||||
	AVB_VERSION_MRP_EVENTS,
 | 
			
		||||
	.event = msrp_event,
 | 
			
		||||
	.notify = msrp_notify
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ static int mvrp_attr_event(void *data, uint64_t now, uint8_t attribute_type, uin
 | 
			
		|||
	struct attr *a;
 | 
			
		||||
	spa_list_for_each(a, &mvrp->attributes, link)
 | 
			
		||||
		if (a->attr.type == attribute_type)
 | 
			
		||||
			avb_mrp_update_state(mvrp->server->mrp, now, a->attr.mrp, event);
 | 
			
		||||
			avb_mrp_attribute_rx_event(a->attr.mrp, now, event);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue