bool openavbAVDECCGetTalkerStreamInfo(openavb_aem_descriptor_stream_io_t *pDescriptorStreamOutput, U16 configIdx, openavb_acmp_TalkerStreamInfo_t *pTalkerStreamInfo)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	// Sanity tests.
	if (!pDescriptorStreamOutput) {
		AVB_LOG_ERROR("openavbAVDECCGetTalkerStreamInfo Invalid descriptor");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}
	if (!pTalkerStreamInfo) {
		AVB_LOG_ERROR("openavbAVDECCGetTalkerStreamInfo Invalid streaminfo");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}
	if (!pDescriptorStreamOutput->stream) {
		AVB_LOG_ERROR("openavbAVDECCGetTalkerStreamInfo Invalid StreamInput descriptor stream");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}

	// Get the destination MAC Address.
	if (!pDescriptorStreamOutput->stream->dest_addr.mac ||
			memcmp(pDescriptorStreamOutput->stream->dest_addr.buffer.ether_addr_octet, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {
		AVB_LOG_DEBUG("openavbAVDECCGetTalkerStreamInfo Invalid stream dest_addr");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}
	memcpy(pTalkerStreamInfo->stream_dest_mac, pDescriptorStreamOutput->stream->dest_addr.mac, ETH_ALEN);
	AVB_LOGF_DEBUG("Talker stream_dest_mac:  " ETH_FORMAT,
		ETH_OCTETS(pTalkerStreamInfo->stream_dest_mac));

	// Get the Stream ID.
	if (!pDescriptorStreamOutput->stream->stream_addr.mac ||
			memcmp(pDescriptorStreamOutput->stream->stream_addr.buffer.ether_addr_octet, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) {
		AVB_LOG_ERROR("openavbAVDECCGetTalkerStreamInfo Invalid stream stream_addr");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return FALSE;
	}
	memcpy(pTalkerStreamInfo->stream_id, pDescriptorStreamOutput->stream->stream_addr.mac, ETH_ALEN);
	U8 *pStreamUID = pTalkerStreamInfo->stream_id + 6;
	*(U16 *)(pStreamUID) = htons(pDescriptorStreamOutput->stream->stream_uid);
	AVB_LOGF_DEBUG("Talker stream_id:  " ETH_FORMAT "/%u",
		ETH_OCTETS(pTalkerStreamInfo->stream_id),
		(((U16) pTalkerStreamInfo->stream_id[6]) << 8) | (U16) pTalkerStreamInfo->stream_id[7]);

	// Get the VLAN ID.
	pTalkerStreamInfo->stream_vlan_id = pDescriptorStreamOutput->stream->vlan_id;

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return TRUE;
}
Exemplo n.º 2
0
bool openavbAvdeccMsgSrvrHndlTalkerStreamIDFromClient(int avdeccMsgHandle, U8 sr_class, const U8 stream_src_mac[6], U16 stream_uid, const U8 stream_dest_mac[6], U16 stream_vlan_id)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC_MSG);

	avdecc_msg_state_t *pState = AvdeccMsgStateListGet(avdeccMsgHandle);
	if (!pState) {
		AVB_LOGF_ERROR("avdeccMsgHandle %d not valid", avdeccMsgHandle);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}

	openavb_tl_data_cfg_t *pCfg = pState->stream;
	if (!pCfg) {
		AVB_LOGF_ERROR("avdeccMsgHandle %d stream not valid", avdeccMsgHandle);
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return false;
	}

	// Update the stream information supplied by the client.
	pCfg->sr_class = sr_class;
	memcpy(pCfg->stream_addr.buffer.ether_addr_octet, stream_src_mac, 6);
	pCfg->stream_addr.mac = &(pCfg->stream_addr.buffer); // Indicate that the MAC Address is valid.
	pCfg->stream_uid = stream_uid;
	memcpy(pCfg->dest_addr.buffer.ether_addr_octet, stream_dest_mac, 6);
	pCfg->dest_addr.mac = &(pCfg->dest_addr.buffer); // Indicate that the MAC Address is valid.
	pCfg->vlan_id = stream_vlan_id;
	AVB_LOGF_DEBUG("Talker-supplied sr_class:  %u", pCfg->sr_class);
	AVB_LOGF_DEBUG("Talker-supplied stream_id:  " ETH_FORMAT "/%u",
		ETH_OCTETS(pCfg->stream_addr.buffer.ether_addr_octet), pCfg->stream_uid);
	AVB_LOGF_DEBUG("Talker-supplied dest_addr:  " ETH_FORMAT,
		ETH_OCTETS(pCfg->dest_addr.buffer.ether_addr_octet));
	AVB_LOGF_DEBUG("Talker-supplied vlan_id:  %u", pCfg->vlan_id);

	// Notify the state machine that we received this information.
	openavbAcmpSMTalker_updateStreamInfo(pCfg);

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
	return true;
}
Exemplo n.º 3
0
bool openavbTLRunListenerInit(int hnd, AVBStreamID_t *streamID)
{
	tl_state_t *pTLState = TLHandleListGet(hnd);
	openavb_tl_cfg_t *pCfg = &pTLState->cfg;
	listener_data_t *pListenerData = pTLState->pPvtListenerData;

	strncpy(pListenerData->ifname, pCfg->ifname, IFNAMSIZ);
	memcpy(&pListenerData->streamID.addr, &pCfg->stream_addr.mac->ether_addr_octet, ETH_ALEN);
	pListenerData->streamID.uniqueID = pCfg->stream_uid;
	memcpy(&pListenerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN);
	pListenerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames;
	pListenerData->tSpec.maxFrameSize = pCfg->max_frame_size;

	AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pListenerData->destAddr));
	AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(streamID));
	listenerStartStream(pTLState);
	
	return TRUE;
}
Exemplo n.º 4
0
/* Find a stream in the list of streams we're handling
 */
clientStream_t* findStream(AVBStreamID_t *streamID)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);
	clientStream_t* ps = NULL;

	// Check for default stream MAC address, and fill it in with
	// interface MAC so that if the talker didn't fill in
	// the stream MAC, we use the one that the endpoint is
	// configured to use.
	//
	// Listener should never pass a default MAC in,
	// because the config code forces the listener to specify MAC in
	// its configuration.  Talker may send a default (empty) MAC in
	// the stream ID, in which case we fill it in.
	//
	// TODO: This is sketchy - it would probably be better to force every
	// client to send fully populated stream IDs.  I think the reason
	// I didn't do that is that it would cause duplicate configuration
	// (in the talker and in the endpoint.)  Perhaps the filling in of
	// the MAC could happen in the endpoint function which calls
	// findstream for the talker.
	//
	static const U8 emptyMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
	if (memcmp(streamID->addr, emptyMAC, ETH_ALEN) == 0) {
		memcpy(streamID->addr, x_cfg.ifmac, ETH_ALEN);
		AVB_LOGF_DEBUG("Replaced default streamID MAC with interface MAC "ETH_FORMAT, ETH_OCTETS(streamID->addr));
	}

	clientStream_t **lpp;
	for(lpp = &x_streamList; *lpp != NULL; lpp = &(*lpp)->next) {
		if (memcmp(streamID->addr, (*lpp)->streamID.addr, ETH_ALEN) == 0
			&& streamID->uniqueID == (*lpp)->streamID.uniqueID)
		{
			ps = *lpp;
			break;
		}
	}
	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return ps;
}
// Returns TRUE, to say we're connected and registers tspec with FQTSS tspec should be initialized
bool openavbTLRunTalkerInit(tl_state_t *pTLState)
{
	openavb_tl_cfg_t *pCfg = &pTLState->cfg;
	talker_data_t *pTalkerData = pTLState->pPvtTalkerData;
	//avtp_stream_t *pStream = (avtp_stream_t *)(pTalkerData->avtpHandle);

	strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ);
 
	// CORE_TODO: It would be good to have some parts of endpoint moved into non-endpoint general code to handle some the stream
	// configuration values.
	// strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ);
	if (pCfg->stream_addr.mac) {
		memcpy(pTalkerData->streamID.addr, pCfg->stream_addr.mac, ETH_ALEN);
	}else {
		AVB_LOG_WARNING("Stream Address Not Set");
	}
		 
	pTalkerData->streamID.uniqueID = pCfg->stream_uid;
	if (pCfg->sr_class == SR_CLASS_A) {
		pTalkerData->classRate = 8000;
		pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ?
					SR_CLASS_A_DEFAULT_VID : pCfg->vlan_id;
		pTalkerData->vlanPCP = SR_CLASS_A_DEFAULT_PRIORITY;
	}
	else if (pCfg->sr_class == SR_CLASS_B) {
		pTalkerData->classRate = 4000;
		pTalkerData->vlanID = pCfg->vlan_id == VLAN_NULL ?
					SR_CLASS_B_DEFAULT_VID : pCfg->vlan_id;
		pTalkerData->vlanPCP = SR_CLASS_B_DEFAULT_PRIORITY;
	}
	memcpy(&pTalkerData->destAddr, &pCfg->dest_addr.mac->ether_addr_octet, ETH_ALEN);

	unsigned int maxBitrate = 0;
	if (pCfg->intf_cb.intf_get_src_bitrate_cb != NULL) {
		maxBitrate = pCfg->intf_cb.intf_get_src_bitrate_cb(pTLState->pMediaQ);
	}
	if (maxBitrate > 0) {
		if (pCfg->map_cb.map_set_src_bitrate_cb != NULL) {
			pCfg->map_cb.map_set_src_bitrate_cb(pTLState->pMediaQ, maxBitrate);
		}

		if (pCfg->map_cb.map_get_max_interval_frames_cb != NULL) {
			unsigned int map_intv_frames = pCfg->map_cb.map_get_max_interval_frames_cb(pTLState->pMediaQ, pTLState->cfg.sr_class);
			pCfg->max_interval_frames = map_intv_frames > 0 ? map_intv_frames : pCfg->max_interval_frames;
		}
	}	
	pTalkerData->tSpec.maxIntervalFrames = pCfg->max_interval_frames;
	pTalkerData->tSpec.maxFrameSize = pCfg->map_cb.map_max_data_size_cb(pTLState->pMediaQ);
	
	// TODO_COREAVB : This wakeRate should also be set in the endpoint case and removed from the tasker.c start stream
	if (!pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ)) {
		pTalkerData->wakeRate = pTalkerData->classRate / pCfg->batch_factor;
	}
	else {
		// Override the class observation interval with the one provided by the mapping module.
		pTalkerData->wakeRate = pCfg->map_cb.map_transmit_interval_cb(pTLState->pMediaQ) / pCfg->batch_factor;
	}

	if_info_t ifinfo;
	openavbCheckInterface(pTalkerData->ifname, &ifinfo);

	pTalkerData->fwmark = openavbQmgrAddStream((SRClassIdx_t)pCfg->sr_class,
					       pTalkerData->wakeRate,
					       pTalkerData->tSpec.maxIntervalFrames,
					       pTalkerData->tSpec.maxFrameSize);

	if (pTalkerData->fwmark == INVALID_FWMARK)
		return FALSE;
	
	AVB_LOGF_INFO("Dest Addr: "ETH_FORMAT, ETH_OCTETS(pTalkerData->destAddr));
	AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(&pTalkerData->streamID));
	talkerStartStream(pTLState);
	
	return TRUE;
}
/* Talker client registers a stream
 */
bool openavbEptSrvrRegisterStream(int h,
                              AVBStreamID_t *streamID,
                              U8 destAddr[],
                              AVBTSpec_t *tSpec,
                              U8 srClass,
                              U8 srRank,
                              U32 latency)
{
	openavbRC rc = OPENAVB_SUCCESS;

	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);

	clientStream_t *ps = findStream(streamID);
	
	if (ps && ps->clientHandle != h) {
		AVB_LOGF_ERROR("Error registering talker; multiple clients for stream %d", streamID->uniqueID);
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return FALSE;
	}

	ps = addStream(h, streamID);
	if (!ps) {
		AVB_LOGF_ERROR("Error registering talker; unable to add client stream %d", streamID->uniqueID);
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return FALSE;
	}
	ps->role = clientTalker;
	ps->tSpec = *tSpec;
	ps->srClass = (SRClassIdx_t)srClass;
	ps->srRank  = srRank;
	ps->latency = latency;
	ps->fwmark = INVALID_FWMARK;

	if (memcmp(ps->destAddr, destAddr, ETH_ALEN) == 0) {
		// no client-supplied address, use MAAP
		struct ether_addr addr;
		ps->hndMaap = openavbMaapAllocate(1, &addr);
		if (ps->hndMaap) {
			memcpy(ps->destAddr, addr.ether_addr_octet, ETH_ALEN);
			strmAttachCb((void*)ps, openavbSrp_LDSt_Stream_Info);		// Inform talker about MAAP
		}
		else {
			AVB_LOG_ERROR("Error registering talker: MAAP failed to allocate MAC address");
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			delStream(ps);
			return FALSE;
		}
	}
	else {
		// client-supplied destination MAC address
		memcpy(ps->destAddr, destAddr, ETH_ALEN);
		ps->hndMaap = NULL;
	}

	// Do SRP talker register
	AVB_LOGF_DEBUG("REGISTER: ps=%p, streamID=%d, tspec=%d,%d, srClass=%d, srRank=%d, latency=%d, da="ETH_FORMAT"",
				   ps, streamID->uniqueID,
				   tSpec->maxFrameSize, tSpec->maxIntervalFrames,
				   ps->srClass, ps->srRank, ps->latency,
				   ETH_OCTETS(ps->destAddr));


	if(x_cfg.noSrp) {
		// we are operating in a mode supporting preconfigured streams; SRP is not in use,
		// so, as a proxy for SRP, which would normally make this call after establishing
		// the stream, call the callback from here
		strmAttachCb((void*)ps, openavbSrp_LDSt_Ready);
	} else {
		// normal SRP operation
		rc = openavbSrpRegisterStream((void*)ps, &ps->streamID,
		                          ps->destAddr, &ps->tSpec,
		                          ps->srClass, ps->srRank,
		                          ps->latency);
		if (!IS_OPENAVB_SUCCESS(rc)) {
			if (ps->hndMaap)
				openavbMaapRelease(ps->hndMaap);
			delStream(ps);
		}
	}

	openavbEndPtLogAllStaticStreams();
	
	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return IS_OPENAVB_SUCCESS(rc);
}