int openavbEptClntOpenSrvrConnection(tl_state_t *pTLState)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);
	struct sockaddr_un server;
	server.sun_family = AF_UNIX;
	snprintf(server.sun_path, UNIX_PATH_MAX, AVB_ENDPOINT_UNIX_PATH);

	int h = socket(AF_UNIX, SOCK_STREAM, 0);
	if (h < 0) {
		AVB_LOGF_DEBUG("Failed to open socket: %s", strerror(errno));
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return AVB_ENDPOINT_HANDLE_INVALID;
	}

	AVB_LOGF_DEBUG("Connecting to %s", server.sun_path);
	int rslt = connect(h, (struct sockaddr*)&server, sizeof(struct sockaddr_un));
	if (rslt < 0) {
		AVB_LOGF_DEBUG("Failed to connect socket: %s", strerror(errno));
		socketClose(h);
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return AVB_ENDPOINT_HANDLE_INVALID;
	}

	AVB_LOG_DEBUG("Connected to endpoint");
	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return h;
}
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;
}
Esempio n. 3
0
// Delete a connection with saved state
//
bool openavbAvdeccClearSavedState(const openavb_tl_data_cfg_t *pListener)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	int i;

	// Delete the saved state matching the supplied one.
	// If the supplied saved state does not match any of the ones already saved, do nothing and return.
	for (i = 0; i < 1000; ++i) {
		const openavb_saved_state_t * pTest = openavbAvdeccGetSavedState(i);
		if (!pTest) {
			break;
		}

		if (strcmp(pTest->listener_friendly_name, pListener->friendly_name) == 0) {
			// We found the index for the item to delete.
			// Delete the item and save the updated file.
			openavbAvdeccDeleteSavedState(i);
			AVB_LOGF_DEBUG("Cleared saved state:  listener_id=\"%s\"", pListener->friendly_name);

			AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
			return true;
		}
	}

	AVB_LOGF_WARNING("Unable to find saved state to clear:  listener_id=\"%s\"", pListener->friendly_name);
	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return false;
}
Esempio n. 4
0
// Open a rawsock for TX or RX
void *pcapRawsockOpen(pcap_rawsock_t* rawsock, const char *ifname, bool rx_mode, bool tx_mode, U16 ethertype, U32 frame_size, U32 num_frames)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK);

	AVB_LOGF_DEBUG("Open, rx=%d, tx=%d, ethertype=%x size=%d, num=%d",	rx_mode, tx_mode, ethertype, frame_size, num_frames);

	baseRawsockOpen(&rawsock->base, ifname, rx_mode, tx_mode, ethertype, frame_size, num_frames);

	if (tx_mode) {
		AVB_LOG_DEBUG("pcap rawsock transmit mode will bypass FQTSS");
	}

	rawsock->handle = 0;

	// Get info about the network device
	if (!simpleAvbCheckInterface(ifname, &(rawsock->base.ifInfo))) {
		AVB_LOGF_ERROR("Creating rawsock; bad interface name: %s", ifname);
		free(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}

	// Deal with frame size.
	if (rawsock->base.frameSize == 0) {
		// use interface MTU as max frames size, if none specified
		rawsock->base.frameSize = rawsock->base.ifInfo.mtu + ETH_HLEN + VLAN_HLEN;
	}
	else if (rawsock->base.frameSize > rawsock->base.ifInfo.mtu + ETH_HLEN + VLAN_HLEN) {
		AVB_LOG_ERROR("Creating rawsock; requested frame size exceeds MTU");
		free(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}

	char errbuf[PCAP_ERRBUF_SIZE];
	rawsock->handle = open_pcap_dev(ifname, rawsock->base.frameSize, errbuf);
	if (!rawsock->handle) {
		AVB_LOGF_ERROR("Cannot open device %s: %s", ifname, errbuf);
		free(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}

	// fill virtual functions table
	rawsock_cb_t *cb = &rawsock->base.cb;
	cb->close = pcapRawsockClose;
	cb->getTxFrame = pcapRawsockGetTxFrame;
	cb->txFrameReady = pcapRawsockTxFrameReady;
	cb->send = pcapRawsockSend;
	cb->getRxFrame = pcapRawsockGetRxFrame;
	cb->rxMulticast = pcapRawsockRxMulticast;
	cb->rxParseHdr = pcapRawsockRxParseHdr;

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
	return rawsock;
}
static bool openavbEptSrvrReceiveFromClient(int h, openavbEndpointMessage_t *msg)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);

	if (!msg) {
		AVB_LOG_ERROR("Receiving message; invalid argument passed");
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return FALSE;
	}
			
	bool ret = FALSE;
	switch (msg->type) {
		case OPENAVB_ENDPOINT_TALKER_REGISTER:
			AVB_LOGF_DEBUG("TalkerRegister from client uid=%d", msg->streamID.uniqueID);
			ret = openavbEptSrvrRegisterStream(h, &msg->streamID,
			                               msg->params.talkerRegister.destAddr,
			                               &msg->params.talkerRegister.tSpec,
			                               msg->params.talkerRegister.srClass,
			                               msg->params.talkerRegister.srRank,
			                               msg->params.talkerRegister.latency);
			break;
		case OPENAVB_ENDPOINT_LISTENER_ATTACH:
			AVB_LOGF_DEBUG("ListenerAttach from client uid=%d", msg->streamID.uniqueID);
			ret = openavbEptSrvrAttachStream(h, &msg->streamID,
			                             msg->params.listenerAttach.lsnrDecl);
			break;
		case OPENAVB_ENDPOINT_CLIENT_STOP:
			AVB_LOGF_DEBUG("Stop from client uid=%d", msg->streamID.uniqueID);
			ret = openavbEptSrvrStopStream(h, &msg->streamID);
			break;
		case OPENAVB_ENDPOINT_VERSION_REQUEST:
			AVB_LOG_DEBUG("Version request from client");
			ret = openavbEptSrvrHndlVerRqstFromClient(h);
			break;
		default:
			AVB_LOG_ERROR("Unexpected message received at server");
			break;
	}

	AVB_LOGF_VERBOSE("Message handled, ret=%d", ret);
	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return ret;
}
Esempio n. 6
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;
}
Esempio n. 7
0
bool openavbAdpOpenSocket(const char* ifname, U16 vlanID, U8 vlanPCP)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ADP);

	hdr_info_t hdr;

#ifndef UBUNTU
	// This is the normal case for most of our supported platforms
	rxSock = openavbRawsockOpen(ifname, TRUE, FALSE, ETHERTYPE_8021Q, ADP_FRAME_LEN, ADP_NUM_BUFFERS);
#else
	rxSock = openavbRawsockOpen(ifname, TRUE, FALSE, ETHERTYPE_AVTP, ADP_FRAME_LEN, ADP_NUM_BUFFERS);
#endif
	txSock = openavbRawsockOpen(ifname, FALSE, TRUE, ETHERTYPE_AVTP, ADP_FRAME_LEN, ADP_NUM_BUFFERS);

	if (txSock && rxSock
		&& openavbRawsockGetAddr(txSock, ADDR_PTR(&intfAddr))
		&& ether_aton_r(ADP_PROTOCOL_ADDR, &adpAddr)
		&& openavbRawsockRxMulticast(rxSock, TRUE, ADDR_PTR(&adpAddr)))
	{
		if (!openavbRawsockRxAVTPSubtype(rxSock, OPENAVB_ADP_AVTP_SUBTYPE | 0x80)) {
			AVB_LOG_DEBUG("RX AVTP Subtype not supported");
		}

		memset(&hdr, 0, sizeof(hdr_info_t));
		hdr.shost = ADDR_PTR(&intfAddr);
		hdr.dhost = ADDR_PTR(&adpAddr);
		hdr.ethertype = ETHERTYPE_AVTP;
		if (vlanID != 0 || vlanPCP != 0) {
			hdr.vlan = TRUE;
			hdr.vlan_pcp = vlanPCP;
			hdr.vlan_vid = vlanID;
			AVB_LOGF_DEBUG("VLAN pcp=%d vid=%d", hdr.vlan_pcp, hdr.vlan_vid);
		}
		if (!openavbRawsockTxSetHdr(txSock, &hdr)) {
			AVB_LOG_ERROR("TX socket Header Failure");
			openavbAdpCloseSocket();
			AVB_TRACE_EXIT(AVB_TRACE_ADP);
			return false;
		}

		AVB_TRACE_EXIT(AVB_TRACE_ADP);
		return true;
	}

	AVB_LOG_ERROR("Invalid socket");
	openavbAdpCloseSocket();

	AVB_TRACE_EXIT(AVB_TRACE_ADP);
	return false;
}
Esempio n. 8
0
static void openavbAdpMessageRxFrameReceive(U32 timeoutUsec)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ADP);

	hdr_info_t hdrInfo;
	unsigned int offset, len;
	U8 *pBuf, *pFrame;

	memset(&hdrInfo, 0, sizeof(hdr_info_t));

	pBuf = (U8 *)openavbRawsockGetRxFrame(rxSock, timeoutUsec, &offset, &len);
	if (pBuf) {
		pFrame = pBuf + offset;

		offset = openavbRawsockRxParseHdr(rxSock, pBuf, &hdrInfo);
		{
#ifndef UBUNTU
			if (hdrInfo.ethertype == ETHERTYPE_8021Q) {
				// Oh!  Need to look past the VLAN tag
				U16 vlan_bits = ntohs(*(U16 *)(pFrame + offset));
				hdrInfo.vlan = TRUE;
				hdrInfo.vlan_vid = vlan_bits & 0x0FFF;
				hdrInfo.vlan_pcp = (vlan_bits >> 13) & 0x0007;
				offset += 2;
				hdrInfo.ethertype = ntohs(*(U16 *)(pFrame + offset));
				offset += 2;
			}
#endif

			// Make sure that this is an AVTP packet
			// (Should always be AVTP if it's to our AVTP-specific multicast address)
			if (hdrInfo.ethertype == ETHERTYPE_AVTP) {
				// parse the PDU only for ADP messages
				if (*(pFrame + offset) == (0x80 | OPENAVB_ADP_AVTP_SUBTYPE)) {
					if (memcmp(hdrInfo.shost, ADDR_PTR(&intfAddr), 6) != 0) { // Not from us!
						openavbAdpMessageRxFrameParse(pFrame + offset, len - offset, &hdrInfo);
					}
				}
			}
			else {
				AVB_LOG_WARNING("Received non-AVTP frame!");
				AVB_LOGF_DEBUG("Unexpected packet data (length %d):", len);
				AVB_LOG_BUFFER(AVB_LOG_LEVEL_DEBUG, pFrame, len, 16);
			}
		}

		// Release the frame
		openavbRawsockRelRxFrame(rxSock, pBuf);
	}
Esempio n. 9
0
// Save the connection to the saved state
//
bool openavbAvdeccSaveState(const openavb_tl_data_cfg_t *pListener, U16 flags, U16 talker_unique_id, const U8 talker_entity_id[8], const U8 controller_entity_id[8])
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	int i;

	// Don't add to the saved state list if fast connect support is not enabled.
	if (!gAvdeccCfg.bFastConnectSupported) {
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return false;
	}

	// If the supplied saved state matches one of the ones already saved, do nothing and return.
	// If the Talker or Controller has changed, delete the old information.
	for (i = 0; i < 1000; ++i) {
		const openavb_saved_state_t * pTest = openavbAvdeccGetSavedState(i);
		if (!pTest) {
			break;
		}

		if (strcmp(pTest->listener_friendly_name, pListener->friendly_name) == 0) {
			if (pTest->flags == flags &&
					pTest->talker_unique_id == talker_unique_id &&
					memcmp(pTest->talker_entity_id, talker_entity_id, 8) == 0 &&
					memcmp(pTest->controller_entity_id, controller_entity_id, 8) == 0) {
				// The supplied data is a match for the existing item.  Do nothing.
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return true;
			}

			// Delete this item.  We will create a new item with the updated information.
			openavbAvdeccDeleteSavedState(i);
			break;
		}
	}

	// Add the supplied state to the list of states.
	openavbAvdeccAddSavedState(pListener->friendly_name, flags, talker_unique_id, talker_entity_id, controller_entity_id);

	AVB_LOGF_DEBUG("New saved state:  listener_id=%s, flags=0x%04x, talker_unique_id=0x%04x, talker_entity_id=" ENTITYID_FORMAT ", controller_entity_id=" ENTITYID_FORMAT,
		pListener->friendly_name,
		flags,
		talker_unique_id,
		ENTITYID_ARGS(talker_entity_id),
		ENTITYID_ARGS(controller_entity_id));

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return true;
}
Esempio n. 10
0
// Pre-set the ethernet header information that will be used on TX frames
bool baseRawsockTxSetHdr(void *pvRawsock, hdr_info_t *pHdr)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
	base_rawsock_t *rawsock = (base_rawsock_t*)pvRawsock;

	if (!VALID_TX_RAWSOCK(rawsock)) {
		AVB_LOG_ERROR("Setting TX header; invalid argument");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return FALSE;
	}

	// source address
	if (pHdr->shost) {
		memcpy(&(rawsock->ethHdr.notag.shost), pHdr->shost, ETH_ALEN);
	}
	// destination address
	if (pHdr->dhost) {
		memcpy(&(rawsock->ethHdr.notag.dhost), pHdr->dhost, ETH_ALEN);
	}

	// VLAN tag?
	if (!pHdr->vlan) {
		// No, set ethertype in normal location
		rawsock->ethHdr.notag.ethertype = htons(rawsock->ethertype);
		// and set ethernet header length
		rawsock->ethHdrLen = sizeof(eth_hdr_t);
	}
	else {
		// Add VLAN tag
		AVB_LOGF_DEBUG("VLAN=%d pcp=%d vid=%d", pHdr->vlan_vid, pHdr->vlan_pcp, pHdr->vlan_vid);

		// Build bitfield with vlan_pcp and vlan_vid.
		// I think CFI bit is alway 0
		u_int16_t bits = 0;
		bits |= (pHdr->vlan_pcp << 13) & 0xE000;
		bits |= pHdr->vlan_vid & 0x0FFF;

		// Create VLAN tag
		rawsock->ethHdr.tagged.vlan.tpip = htons(ETHERTYPE_VLAN);
		rawsock->ethHdr.tagged.vlan.bits = htons(bits);
		rawsock->ethHdr.tagged.ethertype = htons(rawsock->ethertype);
		// and set ethernet header length
		rawsock->ethHdrLen = sizeof(eth_vlan_hdr_t);
	}

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
	return TRUE;
}
bool openavbEndpointServerOpen(void)
{
    AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);
    int i;

    for (i=0; i < POLL_FD_COUNT; i++) {
        fds[i].fd = SOCK_INVALID;
        fds[i].events = 0;
    }

    lsock = socket(AF_UNIX, SOCK_STREAM, 0);
    if (lsock < 0) {
        AVB_LOGF_ERROR("Failed to open socket: %s", strerror(errno));
        goto error;
    }
    // serverAddr is file static
    serverAddr.sun_family = AF_UNIX;
    snprintf(serverAddr.sun_path, UNIX_PATH_MAX, AVB_ENDPOINT_UNIX_PATH);

    int rslt = bind(lsock, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_un));
    if (rslt != 0) {
        AVB_LOGF_ERROR("Failed to create %s: %s", serverAddr.sun_path, strerror(errno));
        AVB_LOG_WARNING("** If endpoint process crashed, run the cleanup script **");
        goto error;
    }

    rslt = listen(lsock, 5);
    if (rslt != 0) {
        AVB_LOGF_ERROR("Failed to listen on socket: %s", strerror(errno));
        goto error;
    }
    AVB_LOGF_DEBUG("Listening on socket: %s", serverAddr.sun_path);

    fds[AVB_ENDPOINT_LISTEN_FDS].fd = lsock;
    fds[AVB_ENDPOINT_LISTEN_FDS].events = POLLIN;

    AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
    return TRUE;

error:
    if (lsock >= 0) {
        close(lsock);
        lsock = -1;
    }
    AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
    return FALSE;
}
Esempio n. 12
0
// Determine if the connection has a saved state
//
bool openavbAvdeccGetSaveStateInfo(const openavb_tl_data_cfg_t *pListener, U16 *p_flags, U16 *p_talker_unique_id, U8 (*p_talker_entity_id)[8], U8 (*p_controller_entity_id)[8])
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	int i;

	// Don't return anything from the saved state list if fast connect support is not enabled.
	if (!gAvdeccCfg.bFastConnectSupported) {
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return false;
	}

	// If the loaded saved state information matches the Listener supplied, return the information for it.
	for (i = 0; i < 1000; ++i) {
		const openavb_saved_state_t * pTest = openavbAvdeccGetSavedState(i);
		if (!pTest) {
			break;
		}

		if (strcmp(pTest->listener_friendly_name, pListener->friendly_name) == 0) {
			AVB_LOGF_DEBUG("Saved state available for listener_id=%s, flags=0x%04x, talker_unique_id=0x%04x, talker_entity_id=" ENTITYID_FORMAT ", controller_entity_id=" ENTITYID_FORMAT,
					pListener->friendly_name,
					pTest->flags,
					pTest->talker_unique_id,
					ENTITYID_ARGS(pTest->talker_entity_id),
					ENTITYID_ARGS(pTest->controller_entity_id));
			if (p_flags) {
				*p_flags = pTest->flags;
			}
			if (p_talker_unique_id) {
				*p_talker_unique_id = pTest->talker_unique_id;
			}
			if (p_talker_entity_id) {
				memcpy(*p_talker_entity_id, pTest->talker_entity_id, 8);
			}
			if (p_controller_entity_id) {
				memcpy(*p_controller_entity_id, pTest->controller_entity_id, 8);
			}
			AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
			return true;
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return false;
}
Esempio n. 13
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;
}
Esempio n. 14
0
// Setup the rawsock to receive multicast packets
bool pcapRawsockRxMulticast(void *pvRawsock, bool add_membership, const U8 addr[ETH_ALEN])
{
	pcap_rawsock_t *rawsock = (pcap_rawsock_t*)pvRawsock;

	struct bpf_program comp_filter_exp;
	char filter_exp[30];

	sprintf(filter_exp, "ether dst %02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

	AVB_LOGF_DEBUG("%s %d %s", __func__, (int)add_membership, filter_exp);

	if (pcap_compile(rawsock->handle, &comp_filter_exp, filter_exp, 0, PCAP_NETMASK_UNKNOWN) < 0) {
		AVB_LOGF_ERROR("Could not parse filter %s: %s", filter_exp, pcap_geterr(rawsock->handle));
		return false;
	}

	if (pcap_setfilter(rawsock->handle, &comp_filter_exp) < 0) {
		AVB_LOGF_ERROR("Could not install filter %s: %s", filter_exp, pcap_geterr(rawsock->handle));
		return false;
	}

	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);
}
Esempio n. 16
0
bool openavbEptClntService(int h, int timeout)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);
	bool rc = FALSE;

	if (h == AVB_ENDPOINT_HANDLE_INVALID) {
		AVB_LOG_ERROR("Client service: invalid socket");
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return FALSE;
	}
	
	struct pollfd fds[1];
	memset(fds, 0, sizeof(struct pollfd));
	fds[0].fd = h;
	fds[0].events = POLLIN;

	AVB_LOG_VERBOSE("Waiting for event...");
	int pRet = poll(fds, 1, timeout);

	if (pRet == 0) {
		AVB_LOG_VERBOSE("Poll timeout");
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return TRUE;
	}
	else if (pRet < 0) {
		if (errno == EINTR) {
			AVB_LOG_VERBOSE("Poll interrupted");
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			return TRUE;
		}
		else {
			AVB_LOGF_ERROR("Poll error: %s", strerror(errno));
		}
	}
	else {
		AVB_LOGF_DEBUG("Poll returned %d events", pRet);
		// only one fd, so it's readable.
		openavbEndpointMessage_t msgBuf;
		memset(&msgBuf, 0, OPENAVB_ENDPOINT_MSG_LEN);
		ssize_t nRead = read(h, &msgBuf, OPENAVB_ENDPOINT_MSG_LEN);
					
		if (nRead < OPENAVB_ENDPOINT_MSG_LEN) {
			// sock closed
			if (nRead == 0) {
				AVB_LOG_ERROR("Socket closed unexpectedly");
			}
			else if (nRead < 0) {
				AVB_LOGF_ERROR("Socket read error: %s", strerror(errno));
			}
			else {
				AVB_LOG_ERROR("Socket read to short");
			}
			socketClose(h);
		}
		else {
			// got a message
			if (openavbEptClntReceiveFromServer(h, &msgBuf)) {
				rc = TRUE;
			}
			else {
				AVB_LOG_ERROR("Invalid message received");
				socketClose(h);
			}
		}
	}
	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return rc;
}
Esempio n. 17
0
// Open a rawsock for TX or RX
void* ringRawsockOpen(ring_rawsock_t *rawsock, const char *ifname, bool rx_mode, bool tx_mode, U16 ethertype, U32 frame_size, U32 num_frames)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK);

	if (!simpleRawsockOpen((simple_rawsock_t*)rawsock, ifname, rx_mode,
			       tx_mode, ethertype, frame_size, num_frames))
	{
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}

	rawsock->pMem = (void*)(-1);

	// Use version 2 headers for the MMAP packet stuff - avoids 32/64
	// bit problems, gives nanosecond timestamps, and allows rx of vlan id
	int val = TPACKET_V2;
	if (setsockopt(rawsock->sock, SOL_PACKET, PACKET_VERSION, &val, sizeof(val)) < 0) {
		AVB_LOGF_ERROR("Creating rawsock; get PACKET_VERSION: %s", strerror(errno));
		ringRawsockClose(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}

	// Get the size of the headers in the ring
	unsigned len = sizeof(val);
	if (getsockopt(rawsock->sock, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
		AVB_LOGF_ERROR("Creating rawsock; get PACKET_HDRLEN: %s", strerror(errno));
		ringRawsockClose(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}
	rawsock->bufHdrSize = TPACKET_ALIGN(val);

	if (rawsock->base.rxMode) {
		rawsock->bufHdrSize = rawsock->bufHdrSize + TPACKET_ALIGN(sizeof(struct sockaddr_ll));
	}
	rawsock->bufferSize = rawsock->base.frameSize + rawsock->bufHdrSize;
	rawsock->frameCount = num_frames;
	AVB_LOGF_DEBUG("frameSize=%d, bufHdrSize=%d(%d+%zu) bufferSize=%d, frameCount=%d",
				   rawsock->base.frameSize, rawsock->bufHdrSize, val, sizeof(struct sockaddr_ll),
				   rawsock->bufferSize, rawsock->frameCount);

	// Get number of bytes in a memory page.  The blocks we ask for
	// must be a multiple of pagesize.  (Actually, it should be
	// (pagesize * 2^N) to avoid wasting memory.)
	int pagesize = getpagesize();
	rawsock->blockSize = pagesize * 4;
	AVB_LOGF_DEBUG("pagesize=%d blockSize=%d", pagesize, rawsock->blockSize);

	// Calculate number of buffers and frames based on blocks
	int buffersPerBlock = rawsock->blockSize / rawsock->bufferSize;
	rawsock->blockCount = rawsock->frameCount / buffersPerBlock + 1;
	rawsock->frameCount = buffersPerBlock * rawsock->blockCount;

	AVB_LOGF_DEBUG("frameCount=%d, buffersPerBlock=%d, blockCount=%d",
				   rawsock->frameCount, buffersPerBlock, rawsock->blockCount);

	// Fill in the kernel structure with our calculated values
	struct tpacket_req s_packet_req;
	memset(&s_packet_req, 0, sizeof(s_packet_req));
	s_packet_req.tp_block_size = rawsock->blockSize;
	s_packet_req.tp_frame_size = rawsock->bufferSize;
	s_packet_req.tp_block_nr = rawsock->blockCount;
	s_packet_req.tp_frame_nr = rawsock->frameCount;

	// Ask the kernel to create the TX_RING or RX_RING
	if (rawsock->base.txMode) {
		if (setsockopt(rawsock->sock, SOL_PACKET, PACKET_TX_RING,
					   (char*)&s_packet_req, sizeof(s_packet_req)) < 0) {
			AVB_LOGF_ERROR("Creating rawsock; TX_RING: %s", strerror(errno));
			ringRawsockClose(rawsock);
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
			return NULL;
		}
		AVB_LOGF_DEBUG("PACKET_%s_RING OK", "TX");
	}
	else {
		if (setsockopt(rawsock->sock, SOL_PACKET, PACKET_RX_RING,
					   (char*)&s_packet_req, sizeof(s_packet_req)) < 0) {
			AVB_LOGF_ERROR("Creating rawsock, RX_RING: %s", strerror(errno));
			ringRawsockClose(rawsock);
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
			return NULL;
		}
		AVB_LOGF_DEBUG("PACKET_%s_RING OK", "TX");
	}

	// Call MMAP to get access to the memory used for the ring
	rawsock->memSize = rawsock->blockCount * rawsock->blockSize;
	AVB_LOGF_DEBUG("memSize=%zu (%d, %d), sock=%d",
				   rawsock->memSize,
				   rawsock->blockCount,
				   rawsock->blockSize,
				   rawsock->sock);
	rawsock->pMem = mmap((void*)0, rawsock->memSize, PROT_READ|PROT_WRITE, MAP_SHARED, rawsock->sock, (off_t)0);
	if (rawsock->pMem == (void*)(-1)) {
		AVB_LOGF_ERROR("Creating rawsock; MMAP: %s", strerror(errno));
		ringRawsockClose(rawsock);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
		return NULL;
	}
	AVB_LOGF_DEBUG("mmap: %p", rawsock->pMem);

	// Initialize the memory
	memset(rawsock->pMem, 0, rawsock->memSize);

	// Initialize the state of the ring
	rawsock->blockIndex = 0;
	rawsock->bufferIndex = 0;
	rawsock->buffersOut = 0;
	rawsock->buffersReady = 0;

	// fill virtual functions table
	rawsock_cb_t *cb = &rawsock->base.cb;
	cb->close = ringRawsockClose;
	cb->getTxFrame = ringRawsockGetTxFrame;
	cb->relTxFrame = ringRawsockRelTxFrame;
	cb->txFrameReady = ringRawsockTxFrameReady;
	cb->send = ringRawsockSend;
	cb->txBufLevel = ringRawsockTxBufLevel;
	cb->rxBufLevel = ringRawsockRxBufLevel;
	cb->getRxFrame = ringRawsockGetRxFrame;
	cb->rxParseHdr = ringRawsockRxParseHdr;
	cb->relRxFrame = ringRawsockRelRxFrame;
	cb->getTXOutOfBuffers = ringRawsockGetTXOutOfBuffers;
	cb->getTXOutOfBuffersCyclic = ringRawsockGetTXOutOfBuffersCyclic;

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK);
	return rawsock;
}
Esempio n. 18
0
// Get a buffer from the ring to use for TX
U8* ringRawsockGetTxFrame(void *pvRawsock, bool blocking, unsigned int *len)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
	ring_rawsock_t *rawsock = (ring_rawsock_t*)pvRawsock;

	// Displays only warning when buffer busy after second try
	int bBufferBusyReported = 0;


	if (!VALID_TX_RAWSOCK(rawsock) || len == NULL) {
		AVB_LOG_ERROR("Getting TX frame; bad arguments");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}
	if (rawsock->buffersOut >= rawsock->frameCount) {
		AVB_LOG_ERROR("Getting TX frame; too many TX buffers in use");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Get pointer to next framebuf.
	volatile struct tpacket2_hdr *pHdr =
		(struct tpacket2_hdr*)(rawsock->pMem
							   + (rawsock->blockIndex * rawsock->blockSize)
							   + (rawsock->bufferIndex * rawsock->bufferSize));
	// And pointer to portion of buffer to be filled with frame
	volatile U8 *pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

	AVB_LOGF_VERBOSE("block=%d, buffer=%d, out=%d, pBuffer=%p, pHdr=%p",
					 rawsock->blockIndex, rawsock->bufferIndex, rawsock->buffersOut,
					 pBuffer, pHdr);

	// Check if buffer ready for user
	// In send mode, we want to see TP_STATUS_AVAILABLE
	while (pHdr->tp_status != TP_STATUS_AVAILABLE)
	{
		switch (pHdr->tp_status) {
			case TP_STATUS_SEND_REQUEST:
			case TP_STATUS_SENDING:
				if (blocking) {
#if 0
// We should be able to poll on the socket to wait for the buffer to
// be ready, but it doesn't work (at least on 2.6.37).
// Keep this code, because it may work on newer kernels
					// poll until tx buffer is ready
					struct pollfd pfd;
					pfd.fd = rawsock->sock;
					pfd.events = POLLWRNORM;
					pfd.revents = 0;
					int ret = poll(&pfd, 1, -1);
					if (ret < 0 && errno != EINTR) {
						AVB_LOGF_DEBUG("getting TX frame; poll failed: %s", strerror(errno));
					}
#else
					// Can't poll, so sleep instead to avoid tight loop
					if(0 == bBufferBusyReported) {
						if(!rawsock->txOutOfBuffer) {
							// Display this info only once just to let know that something like this happened
							AVB_LOGF_INFO("Getting TX frame (sock=%d): TX buffer busy", rawsock->sock);
						}

						++rawsock->txOutOfBuffer;
						++rawsock->txOutOfBufferCyclic;
					} else if(1 == bBufferBusyReported) {
						//Display this warning if buffer was busy more than once because it might influence late/lost
						AVB_LOGF_WARNING("Getting TX frame (sock=%d): TX buffer busy after usleep(50) verify if there are any lost/late frames", rawsock->sock);
					}

					++bBufferBusyReported;

					usleep(50);
#endif
				}
				else {
					AVB_LOG_DEBUG("Non-blocking, return NULL");
					AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
					return NULL;
				}
				break;
			case TP_STATUS_WRONG_FORMAT:
			default:
				pHdr->tp_status = TP_STATUS_AVAILABLE;
				break;
		}
	}

	// Remind client how big the frame buffer is
	if (len)
		*len = rawsock->base.frameSize;

	// increment indexes to point to next buffer
	if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
		rawsock->bufferIndex = 0;
		if (++(rawsock->blockIndex) >= rawsock->blockCount) {
			rawsock->blockIndex = 0;
		}
	}

	// increment the count of buffers held by client
	rawsock->buffersOut += 1;

	// warn if too many are out
	if (rawsock->buffersOut >= (rawsock->frameCount * 4)/5) {
		AVB_LOGF_WARNING("Getting TX frame; consider increasing buffers: count=%d, out=%d",
						 rawsock->frameCount, rawsock->buffersOut);
	}

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
	return (U8*)pBuffer;
}
Esempio n. 19
0
// callback function - called for each name/value pair by ini parsing library
static int openavbIniCfgCallback(void *user, const char *tlSection, const char *name, const char *value)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	openavb_tl_data_cfg_t *pCfg = (openavb_tl_data_cfg_t *)user;

	AVB_LOGF_DEBUG("name=[%s] value=[%s]", name, value);

	bool valOK = FALSE;
	char *pEnd;

	if (MATCH(name, "role")) {
		if (MATCH(value, "talker")) {
			pCfg->role = AVB_ROLE_TALKER;
			valOK = TRUE;
		}
		else if (MATCH(value, "listener")) {
			pCfg->role = AVB_ROLE_LISTENER;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "initial_state")) {
		if (MATCH(value, "running")) {
			pCfg->initial_state = TL_INIT_STATE_RUNNING;
			valOK = TRUE;
		}
		else if (MATCH(value, "stopped")) {
			pCfg->initial_state = TL_INIT_STATE_STOPPED;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "dest_addr")) {
		valOK = parse_mac(value, &pCfg->dest_addr);
	}
	else if (MATCH(name, "stream_addr")) {
		valOK = parse_mac(value, &pCfg->stream_addr);
	}
	else if (MATCH(name, "stream_uid")) {
		errno = 0;
		pCfg->stream_uid = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->stream_uid <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_interval_frames")) {
		errno = 0;
		pCfg->max_interval_frames = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_interval_frames <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_frame_size")) {
		errno = 0;
		pCfg->max_frame_size = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_interval_frames <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "sr_class")) {
		if (strlen(value) == 1) {
			if (tolower(value[0]) == 'a') {
				pCfg->sr_class = SR_CLASS_A;
				valOK = TRUE;
			}
			else if (tolower(value[0]) == 'b') {
				pCfg->sr_class = SR_CLASS_B;
				valOK = TRUE;
			}
		}
	}
	else if (MATCH(name, "sr_rank")) {
		if (strlen(value) == 1) {
			if (value[0] == '1') {
				pCfg->sr_rank = SR_RANK_REGULAR;
				valOK = TRUE;
			}
			else if (value[0] == '0') {
				pCfg->sr_rank = SR_RANK_EMERGENCY;
				valOK = TRUE;
			}
		}
	}
	else if (MATCH(name, "max_transit_usec")) {
		errno = 0;
		pCfg->max_transit_usec = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_transit_usec <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_transmit_deficit_usec")) {
		errno = 0;
		pCfg->max_transmit_deficit_usec = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_transmit_deficit_usec <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "internal_latency")) {
		errno = 0;
		pCfg->internal_latency = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->internal_latency <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "batch_factor")) {
		errno = 0;
		pCfg->batch_factor = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->batch_factor > 0
			&& pCfg->batch_factor <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_stale")) {
		errno = 0;
		pCfg->max_stale = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_stale >= 0
			&& pCfg->max_stale <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "raw_tx_buffers")) {
		errno = 0;
		pCfg->raw_tx_buffers = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->raw_tx_buffers <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "raw_rx_buffers")) {
		errno = 0;
		pCfg->raw_rx_buffers = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->raw_rx_buffers <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "report_seconds")) {
		errno = 0;
		pCfg->report_seconds = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& (int)pCfg->report_seconds >= 0
			&& pCfg->report_seconds <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "start_paused")) {
		// ignore this item - tl_host doesn't use it because
		// it pauses before reading any of its streams.
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& tmp >= 0
			&& tmp <= 1) {
			pCfg->start_paused = (tmp == 1);
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "vlan_id")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		// vlanID is 12 bit field
		if (*pEnd == '\0' && errno == 0
			&& tmp >= 0x0
			&& tmp <= 0xFFF) {
			pCfg->vlan_id = tmp;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "fixed_timestamp")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		if (*pEnd == '\0' && errno == 0) {
			pCfg->fixed_timestamp = tmp;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "spin_wait")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		if (*pEnd == '\0' && errno == 0) {
			pCfg->spin_wait = (tmp == 1);
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "tx_blocking_in_intf")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		if (*pEnd == '\0' && errno == 0) {
			pCfg->tx_blocking_in_intf = tmp;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "thread_rt_priority")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		if (*pEnd == '\0' && errno == 0) {
			pCfg->thread_rt_priority = tmp;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "thread_affinity")) {
		errno = 0;
		unsigned long tmp;
		tmp = strtoul(value, &pEnd, 0);
		if (*pEnd == '\0' && errno == 0) {
			pCfg->thread_affinity = tmp;
			valOK = TRUE;
		}
	}

	else if (MATCH(name, "friendly_name")) {
		strncpy(pCfg->friendly_name, value, FRIENDLY_NAME_SIZE - 1);
		valOK = TRUE;
	}

	else if (MATCH(name, "current_sampling_rate")) {
		errno = 0;
		pCfg->current_sampling_rate = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->current_sampling_rate <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "sampling_rates")) {
		errno = 0;
		memset(pCfg->sampling_rates,0,sizeof(pCfg->sampling_rates));
		char *rate, *copy;
		copy = strdup(value);
		rate = strtok(copy,",");
		int i = 0,break_flag = 0;
		while (rate != NULL )
		{
			pCfg->sampling_rates[i] = strtol(rate,&pEnd, 10);
			if (*pEnd != '\0' || errno != 0
				|| pCfg->sampling_rates[i] > UINT32_MAX)
			{
				break_flag = 1;
				break;
			}
			rate = strtok(NULL,",");
			i++;
		}
		if (break_flag != 1)
		{
			valOK = TRUE;
			pCfg->sampling_rates_count = i;
		}
	}
	else if (strcmp(name, "intf_nv_audio_rate") == 0) {
		long int val = strtol(value, &pEnd, 10);
		if (val >= AVB_AUDIO_RATE_8KHZ && val <= AVB_AUDIO_RATE_192KHZ) {
			pCfg->audioRate = val;
			valOK = TRUE;
		}
		else {
			AVB_LOG_ERROR("Invalid audio rate configured for intf_nv_audio_rate.");
			pCfg->audioRate = AVB_AUDIO_RATE_44_1KHZ;
		}
	}
	else if (strcmp(name, "intf_nv_audio_bit_depth") == 0) {
		long int val = strtol(value, &pEnd, 10);
		if (val >= AVB_AUDIO_BIT_DEPTH_1BIT && val <= AVB_AUDIO_BIT_DEPTH_64BIT) {
			pCfg->audioBitDepth = val;
			valOK = TRUE;
		}
		else {
			AVB_LOG_ERROR("Invalid audio type configured for intf_nv_audio_bits.");
			pCfg->audioBitDepth = AVB_AUDIO_BIT_DEPTH_24BIT;
		}
	}
	else if (strcmp(name, "intf_nv_audio_channels") == 0) {
		long int val = strtol(value, &pEnd, 10);
		if (val >= AVB_AUDIO_CHANNELS_1 && val <= AVB_AUDIO_CHANNELS_8) {
			pCfg->audioChannels = val;
			valOK = TRUE;
		}
		else {
			AVB_LOG_ERROR("Invalid audio channels configured for intf_nv_audio_channels.");
			pCfg->audioChannels = AVB_AUDIO_CHANNELS_2;
		}
	}
	else if (MATCH(name, "map_fn")) {
		errno = 0;
		memset(pCfg->map_fn,0,sizeof(pCfg->map_fn));
		strncpy(pCfg->map_fn,value,sizeof(pCfg->map_fn)-1);
		valOK = TRUE;
	}

	else {
		// Ignored item.
		AVB_LOGF_DEBUG("Unhandled configuration item: name=%s, value=%s", name, value);

		// Don't abort for this item.
		valOK = TRUE;
	}

	if (!valOK) {
		// bad value
		AVB_LOGF_ERROR("Invalid value: name=%s, value=%s", name, value);
		return 0;
	}

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);

	return 1; // OK
}
void openavbEptSrvrService(void)
{
    AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);
    struct sockaddr_un addrClient;
    socklen_t lenAddr;
    int i, j;
    int  csock;

    int nfds = POLL_FD_COUNT;
    int pRet;

    AVB_LOG_VERBOSE("Waiting for event...");
    pRet = poll(fds, nfds, 1000);

    if (pRet == 0) {
        AVB_LOG_VERBOSE("poll timeout");
    }
    else if (pRet < 0) {
        if (errno == EINTR) {
            AVB_LOG_VERBOSE("Poll interrupted");
        }
        else {
            AVB_LOGF_ERROR("Poll error: %s", strerror(errno));
        }
    }
    else {
        AVB_LOGF_VERBOSE("Poll returned %d events", pRet);
        for (i=0; i<nfds; i++) {
            if (fds[i].revents != 0) {
                AVB_LOGF_VERBOSE("%d sock=%d, event=0x%x, revent=0x%x", i, fds[i].fd, fds[i].events, fds[i].revents);

                if (i == AVB_ENDPOINT_LISTEN_FDS) {
                    // listen sock - indicates new connection from client
                    lenAddr = sizeof(addrClient);
                    csock = accept(lsock, (struct sockaddr*)&addrClient, &lenAddr);
                    if (csock < 0) {
                        AVB_LOGF_ERROR("Failed to accept connection: %s", strerror(errno));
                    }
                    else {
                        for (j = 0; j < POLL_FD_COUNT; j++) {
                            if (fds[j].fd == SOCK_INVALID) {
                                fds[j].fd = csock;
                                fds[j].events = POLLIN;
                                break;
                            }
                        }
                        if (j >= POLL_FD_COUNT) {
                            AVB_LOG_ERROR("Too many client connections");
                            close(csock);
                        }
                    }
                }
                else {
                    csock = fds[i].fd;
                    openavbEndpointMessage_t  msgBuf;
                    memset(&msgBuf, 0, OPENAVB_ENDPOINT_MSG_LEN);
                    ssize_t nRead = read(csock, &msgBuf, OPENAVB_ENDPOINT_MSG_LEN);
                    AVB_LOGF_VERBOSE("Socket read h=%d,fd=%d: read=%zu, expect=%zu", i, csock, nRead, OPENAVB_ENDPOINT_MSG_LEN);

                    if (nRead < OPENAVB_ENDPOINT_MSG_LEN) {
                        // sock closed
                        if (nRead == 0) {
                            AVB_LOGF_DEBUG("Socket closed, h=%d", i);
                        }
                        else if (nRead < 0) {
                            AVB_LOGF_ERROR("Socket read, h=%d: %s", i, strerror(errno));
                        }
                        else {
                            AVB_LOGF_ERROR("Short read, h=%d", i);
                        }
                        socketClose(i);
                    }
                    else {
                        // got a message
                        if (!openavbEptSrvrReceiveFromClient(i, &msgBuf)) {
                            AVB_LOG_ERROR("Failed to handle message");
                            socketClose(i);
                        }
                    }
                }
            }
        }
    }
    AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
}
Esempio n. 21
0
// callback function - called for each name/value pair by ini parsing library
static int openavbTLCfgCallback(void *user, const char *tlSection, const char *name, const char *value)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	parse_ini_data_t *pParseIniData = (parse_ini_data_t *)user;
	openavb_tl_cfg_t *pCfg = pParseIniData->pCfg;
	openavb_tl_cfg_name_value_t *pNVCfg = pParseIniData->pNVCfg;
	tl_state_t *pTLState = pParseIniData->pTLState;

	AVB_LOGF_DEBUG("name=[%s] value=[%s]", name, value);

	bool valOK = FALSE;
	char *pEnd;
	int i;

	if (MATCH(name, "role")) {
		if (MATCH(value, "talker")) {
			pCfg->role = AVB_ROLE_TALKER;
			valOK = TRUE;
		}
		else if (MATCH(value, "listener")) {
			pCfg->role = AVB_ROLE_LISTENER;
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "dest_addr")) {
		valOK = parse_mac(value, &pCfg->dest_addr);
	}
	else if (MATCH(name, "stream_addr")) {
		valOK = parse_mac(value, &pCfg->stream_addr);
	}
	else if (MATCH(name, "stream_uid")) {
		errno = 0;
		pCfg->stream_uid = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->stream_uid <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_interval_frames")) {
		errno = 0;
		pCfg->max_interval_frames = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_interval_frames <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_frame_size")) {
		errno = 0;
		pCfg->max_frame_size = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_interval_frames <= UINT16_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "sr_class")) {
		if (strlen(value) == 1) {
			if (tolower(value[0]) == 'a') {
				pCfg->sr_class = SR_CLASS_A;
				valOK = TRUE;
			}
			else if (tolower(value[0]) == 'b') {
				pCfg->sr_class = SR_CLASS_B;
				valOK = TRUE;
			}
		}
	}
	else if (MATCH(name, "sr_rank")) {
		if (strlen(value) == 1) {
			if (value[0] == '1') {
				pCfg->sr_rank = SR_RANK_REGULAR;
				valOK = TRUE;
			}
			else if (value[0] == '0') {
				pCfg->sr_rank = SR_RANK_EMERGENCY;
				valOK = TRUE;
			}
		}
	}
	else if (MATCH(name, "max_transit_usec")) {
		errno = 0;
		pCfg->max_transit_usec = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_transit_usec <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_transmit_deficit_usec")) {
		errno = 0;
		pCfg->max_transmit_deficit_usec = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_transmit_deficit_usec <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "internal_latency")) {
		errno = 0;
		pCfg->internal_latency = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->internal_latency <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "batch_factor")) {
		errno = 0;
		pCfg->batch_factor = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->batch_factor > 0
			&& pCfg->batch_factor <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "max_stale")) {
		errno = 0;
		pCfg->max_stale = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->max_stale >= 0
			&& pCfg->max_stale <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "raw_tx_buffers")) {
		errno = 0;
		pCfg->raw_tx_buffers = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->raw_tx_buffers <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "raw_rx_buffers")) {
		errno = 0;
		pCfg->raw_rx_buffers = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& pCfg->raw_rx_buffers <= UINT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "report_seconds")) {
		errno = 0;
		pCfg->report_seconds = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& (int)pCfg->report_seconds >= 0
			&& pCfg->report_seconds <= INT32_MAX)
			valOK = TRUE;
	}
	else if (MATCH(name, "start_paused")) {
		// ignore this item - tl_host doesn't use it because
		// it pauses before reading any of its streams.
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 10);
		if (*pEnd == '\0' && errno == 0
			&& tmp >= 0
			&& tmp <= 1) {
			pCfg->start_paused = (tmp == 1);
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "ifname")) {
		if_info_t ifinfo;
		if (openavbCheckInterface(value, &ifinfo)) {
			strncpy(pCfg->ifname, value, IFNAMSIZ - 1);
			valOK = TRUE;
		}
	}
	else if (MATCH(name, "vlan_id")) {
		errno = 0;
		long tmp;
		tmp = strtol(value, &pEnd, 0);
		// vlanID is 12 bit field
		if (*pEnd == '\0' && errno == 0
			&& tmp >= 0x0
			&& tmp <= 0xFFF) {
			pCfg->vlan_id = tmp;
			valOK = TRUE;
		}
	}

	else if (MATCH(name, "map_lib")) {
		if (pTLState->mapLib.libName)
			free(pTLState->mapLib.libName);
		pTLState->mapLib.libName = strdup(value);
		valOK = TRUE;
	}
	else if (MATCH(name, "map_fn")) {
		if (pTLState->mapLib.funcName)
			free(pTLState->mapLib.funcName);
		pTLState->mapLib.funcName = strdup(value);
		valOK = TRUE;
	}

	else if (MATCH(name, "intf_lib")) {
		if (pTLState->intfLib.libName)
			free(pTLState->intfLib.libName);
		pTLState->intfLib.libName = strdup(value);
		valOK = TRUE;
	}
	else if (MATCH(name, "intf_fn")) {
		if (pTLState->intfLib.funcName)
			free(pTLState->intfLib.funcName);
		pTLState->intfLib.funcName = strdup(value);
		valOK = TRUE;
	}

	else if (MATCH_LEFT(name, "intf_nv_", 8)
		|| MATCH_LEFT(name, "map_nv_", 7)) {
		// Need to save the interface and mapping module configuration
		// until later (after those libraries are loaded.)

		// check if this setting replaces an earlier one
		for (i = 0; i < pNVCfg->nLibCfgItems; i++) {
			if (MATCH(name, pNVCfg->libCfgNames[i])) {
				if (pNVCfg->libCfgValues[i])
					free(pNVCfg->libCfgValues[i]);
				pNVCfg->libCfgValues[i] = strdup(value);
				valOK = TRUE;
			}
		}
		if (i >= pNVCfg->nLibCfgItems) {
			// is a new name/value
			if (i >= MAX_LIB_CFG_ITEMS) {
				AVB_LOG_ERROR("Too many INI settings for interface/mapping modules");
			}
			else {
				pNVCfg->libCfgNames[i] = strdup(name);
				pNVCfg->libCfgValues[i] = strdup(value);
				pNVCfg->nLibCfgItems++;
				valOK = TRUE;
			}
		}
	}
	else {
		// unmatched item, fail
		AVB_LOGF_ERROR("Unrecognized configuration item: name=%s", name);
		return 0;
	}

	if (!valOK) {
		// bad value
		AVB_LOGF_ERROR("Invalid value: name=%s, value=%s", name, value);
		return 0;
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);

	return 1; // OK
}
/* Talker callback comes from endpoint, to indicate when listeners
 * come and go. We may need to start or stop the talker thread.
 */
void openavbEptClntNotifyTlkrOfSrpCb(int                      endpointHandle,
                                 AVBStreamID_t           *streamID,
                                 char                    *ifname,
                                 U8                       destAddr[],
                                 openavbSrpLsnrDeclSubtype_t  lsnrDecl,
                                 U8                       srClass,
                                 U32                      classRate,
                                 U16                      vlanID,
                                 U8                       priority,
                                 U16                      fwmark)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	tl_state_t *pTLState = TLHandleListGet(endpointHandle);
	talker_data_t *pTalkerData = pTLState->pPvtTalkerData;

	if (!pTLState) {
		AVB_LOG_WARNING("Unable to get talker from endpoint handle.");
		return;
	}

	// If not a talker, ignore this callback.
	if (pTLState->cfg.role != AVB_ROLE_TALKER) {
		AVB_LOG_DEBUG("Ignoring Talker callback");
		return;
	}

	AVB_LOGF_DEBUG("%s streaming=%d, lsnrDecl=%d", __FUNCTION__, pTLState->bStreaming, lsnrDecl);

	openavb_tl_cfg_t *pCfg = &pTLState->cfg;

	if (!pTLState->bStreaming) {
		if (lsnrDecl == openavbSrp_LDSt_Ready
			|| lsnrDecl == openavbSrp_LDSt_Ready_Failed) {

			// Save the data provided by endpoint/SRP
			if (!pCfg->ifname[0]) {
				strncpy(pTalkerData->ifname, ifname, IFNAMSIZ);
			} else {
				strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ);
			}
			memcpy(&pTalkerData->streamID, streamID, sizeof(AVBStreamID_t));
			memcpy(&pTalkerData->destAddr, destAddr, ETH_ALEN);
			pTalkerData->srClass = srClass;
			pTalkerData->classRate = classRate;
			pTalkerData->vlanID = vlanID;
			pTalkerData->vlanPCP = priority;
			pTalkerData->fwmark = fwmark;

			// We should start streaming
			AVB_LOGF_INFO("Starting stream: "STREAMID_FORMAT, STREAMID_ARGS(streamID));
			talkerStartStream(pTLState);
		}
		else if (lsnrDecl == openavbSrp_LDSt_Stream_Info) {
			// Stream information is available does NOT mean listener is ready. Stream not started yet.
			if (!pCfg->ifname[0]) {
				strncpy(pTalkerData->ifname, ifname, IFNAMSIZ);
			} else {
				strncpy(pTalkerData->ifname, pCfg->ifname, IFNAMSIZ);
			}
			memcpy(&pTalkerData->streamID, streamID, sizeof(AVBStreamID_t));
			memcpy(&pTalkerData->destAddr, destAddr, ETH_ALEN);
			pTalkerData->srClass = srClass;
			pTalkerData->classRate = classRate;
			pTalkerData->vlanID = vlanID;
			pTalkerData->vlanPCP = priority;
			pTalkerData->fwmark = fwmark;
		}
	}
	else {
		if (lsnrDecl != openavbSrp_LDSt_Ready
			&& lsnrDecl != openavbSrp_LDSt_Ready_Failed) {
			// Nobody is listening any more
			AVB_LOGF_INFO("Stopping stream: "STREAMID_FORMAT, STREAMID_ARGS(streamID));
			talkerStopStream(pTLState);
		}
	}

	// Let the AVDECC Msg server know our current stream ID, in case it was updated by MAAP.
	if (pTLState->avdeccMsgHandle != AVB_AVDECC_MSG_HANDLE_INVALID) {
		if (!openavbAvdeccMsgClntTalkerStreamID(pTLState->avdeccMsgHandle,
				pTalkerData->srClass, pTalkerData->streamID.addr, pTalkerData->streamID.uniqueID,
				pTalkerData->destAddr, pTalkerData->vlanID)) {
			AVB_LOG_ERROR("openavbAvdeccMsgClntTalkerStreamID() failed");
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_TL);
}
Esempio n. 23
0
static void openavbAdpMessageRxFrameParse(U8* payload, int payload_len, hdr_info_t *hdr)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ADP);

	openavb_adp_control_header_t adpHeader;
	openavb_adp_data_unit_t adpPdu;

#if 0
	AVB_LOGF_DEBUG("openavbAdpMessageRxFrameParse packet data (length %d):", payload_len);
	AVB_LOG_BUFFER(AVB_LOG_LEVEL_DEBUG, payload, payload_len, 16);
#endif

	U8 *pSrc = payload;
	{
		// AVTP Control Header
		openavb_adp_control_header_t *pDst = &adpHeader;

		BIT_B2DNTOHB(pDst->cd, pSrc, 0x80, 7, 0);
		BIT_B2DNTOHB(pDst->subtype, pSrc, 0x7f, 0, 1);
		BIT_B2DNTOHB(pDst->sv, pSrc, 0x80, 7, 0);
		BIT_B2DNTOHB(pDst->version, pSrc, 0x70, 4, 0);
		BIT_B2DNTOHB(pDst->message_type, pSrc, 0x0f, 0, 1);
		BIT_B2DNTOHB(pDst->valid_time, pSrc, 0xf800, 11, 0);
		BIT_B2DNTOHS(pDst->control_data_length, pSrc, 0x07ff, 0, 2);
		OCT_B2DMEMCP(pDst->entity_id, pSrc);
	}

	if (adpHeader.subtype == OPENAVB_ADP_AVTP_SUBTYPE &&
			(adpHeader.message_type == OPENAVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER ||
			 (gAvdeccCfg.bFastConnectSupported && adpHeader.message_type == OPENAVB_ADP_MESSAGE_TYPE_ENTITY_AVAILABLE))) {
		// ADP PDU
		openavb_adp_data_unit_t *pDst = &adpPdu;

		OCT_B2DMEMCP(pDst->entity_model_id, pSrc);
		OCT_B2DNTOHL(pDst->entity_capabilities, pSrc);
		OCT_B2DNTOHS(pDst->talker_stream_sources, pSrc);
		OCT_B2DNTOHS(pDst->talker_capabilities, pSrc);
		OCT_B2DNTOHS(pDst->listener_stream_sinks, pSrc);
		OCT_B2DNTOHS(pDst->listener_capabilities, pSrc);
		OCT_B2DNTOHL(pDst->controller_capabilities, pSrc);
		OCT_B2DNTOHL(pDst->available_index, pSrc);
		OCT_B2DMEMCP(pDst->gptp_grandmaster_id, pSrc);
		OCT_B2DNTOHB(pDst->gptp_domain_number, pSrc);
		OCT_B2DMEMCP(pDst->reserved0, pSrc);
		OCT_B2DNTOHS(pDst->identify_control_index, pSrc);
		OCT_B2DNTOHS(pDst->interface_index, pSrc);
		OCT_B2DMEMCP(pDst->association_id, pSrc);
		OCT_B2DMEMCP(pDst->reserved1, pSrc);

		if (adpHeader.message_type == OPENAVB_ADP_MESSAGE_TYPE_ENTITY_DISCOVER) {
			// Update the interface state machine
			openavbAdpSMAdvertiseInterfaceSet_entityID(adpHeader.entity_id);
			openavbAdpSMAdvertiseInterfaceSet_rcvdDiscover(TRUE);
		}
		else {
			// See if Fast Connect is waiting for this device to be available.
			if (adpPdu.talker_stream_sources > 0) {
				openavbAcmpSMListenerSet_talkerTestFastConnect(adpHeader.entity_id);
			}
		}
	}

	AVB_TRACE_EXIT(AVB_TRACE_ADP);
}
Esempio n. 24
0
static gboolean
bus_message(GstBus *bus, GstMessage *message, void *pv)
{
	switch (GST_MESSAGE_TYPE(message))
	{
		case GST_MESSAGE_ERROR:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_error(message, &err, &dbg_info);
			AVB_LOGF_ERROR("GStreamer ERROR message from element %s: %s",
			               GST_OBJECT_NAME(message->src),
			               err->message);
			AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_WARNING:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_warning(message, &err, &dbg_info);
			AVB_LOGF_WARNING("GStreamer WARNING message from element %s: %s",
			                 GST_OBJECT_NAME(message->src),
			                 err->message);
			AVB_LOGF_WARNING("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_INFO:
		{
			GError *err = NULL;
			gchar *dbg_info = NULL;

			gst_message_parse_info(message, &err, &dbg_info);
			AVB_LOGF_ERROR("GStreamer INFO message from element %s: %s",
			               GST_OBJECT_NAME(message->src),
			               err->message);
			AVB_LOGF_ERROR("Additional info: %s\n", (dbg_info) ? dbg_info : "none");
			g_error_free(err);
			g_free(dbg_info);
			break;
		}
		case GST_MESSAGE_STATE_CHANGED:
		{
			GstState old_state, new_state;
			gst_message_parse_state_changed(message, &old_state, &new_state, NULL);
			AVB_LOGF_DEBUG("Element %s changed state from %s to %s",
			               GST_OBJECT_NAME(message->src),
			               gst_element_state_get_name(old_state),
			               gst_element_state_get_name(new_state));
			break;
		}
		case GST_MESSAGE_STREAM_STATUS:
		{
			// not so valuable
			break;
		}
		case GST_MESSAGE_EOS:
			AVB_LOG_INFO("EOS received");
			break;
		default:
			AVB_LOGF_INFO("GStreamer '%s' message from element %s",
			              gst_message_type_get_name(GST_MESSAGE_TYPE(message)),
			              GST_OBJECT_NAME(message->src));
			break;
	}

	return TRUE;
}
Esempio n. 25
0
static int cfgCallback(void *user, const char *section, const char *name, const char *value)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);

	if (!user || !section || !name || !value) {
		AVB_LOG_ERROR("Config: invalid arguments passed to callback");
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return 0;
	}
	
	openavb_endpoint_cfg_t *pCfg = (openavb_endpoint_cfg_t*)user;
	
	AVB_LOGF_DEBUG("name=[%s] value=[%s]", name, value);

	bool valOK = FALSE;
	char *pEnd;

	if (MATCH(section, "network"))
	{
		if (MATCH(name, "ifname"))
		{
			if_info_t ifinfo;
			if (openavbCheckInterface(value, &ifinfo)) {
				strncpy(pCfg->ifname, value, IFNAMSIZ - 1);
				memcpy(pCfg->ifmac, &ifinfo.mac, ETH_ALEN);
				pCfg->ifindex = ifinfo.index;
				pCfg->mtu = ifinfo.mtu;
				valOK = TRUE;
			}
		}
		else if (MATCH(name, "link_kbit")) {
			errno = 0;
			pCfg->link_kbit = strtoul(value, &pEnd, 10);
			if (*pEnd == '\0' && errno == 0)
				valOK = TRUE;
		}
		else if (MATCH(name, "nsr_kbit")) {
			errno = 0;
			pCfg->nsr_kbit = strtoul(value, &pEnd, 10);
			if (*pEnd == '\0' && errno == 0)
				valOK = TRUE;
		}
		else {
			// unmatched item, fail
			AVB_LOGF_ERROR("Unrecognized configuration item: section=%s, name=%s", section, name);
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			return 0;
		}
	}
	else if (MATCH(section, "ptp"))
	{
		if (MATCH(name, "start_options")) {
			pCfg->ptp_start_opts = strdup(value);
			valOK = TRUE;
		}
		else {
			// unmatched item, fail
			AVB_LOGF_ERROR("Unrecognized configuration item: section=%s, name=%s", section, name);
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			return 0;
		}
	}
	else if (MATCH(section, "fqtss"))
	{
		if (MATCH(name, "mode")) {
			errno = 0;
			pCfg->fqtss_mode = strtoul(value, &pEnd, 10);
			if (*pEnd == '\0' && errno == 0)
				valOK = TRUE;
		}
		else {
			// unmatched item, fail
			AVB_LOGF_ERROR("Unrecognized configuration item: section=%s, name=%s", section, name);
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			return 0;
		}
	}
	else if (MATCH(section, "srp"))
	{
		if (MATCH(name, "preconfigured")) {
			errno = 0;
			unsigned temp = strtoul(value, &pEnd, 10);
			if (*pEnd == '\0' && errno == 0) {
				valOK = TRUE;
				if (temp == 1)
					pCfg->noSrp = TRUE;
				else
					pCfg->noSrp = FALSE;
			}
		}
		else if (MATCH(name, "gptp_asCapable_not_required")) {
			errno = 0;
			unsigned temp = strtoul(value, &pEnd, 10);
			if (*pEnd == '\0' && errno == 0) {
				valOK = TRUE;
				if (temp == 1)
					pCfg->bypassAsCapableCheck = TRUE;
				else
					pCfg->bypassAsCapableCheck = FALSE;
			}
		}
		else {
			// unmatched item, fail
			AVB_LOGF_ERROR("Unrecognized configuration item: section=%s, name=%s", section, name);
			AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
			return 0;
		}
	}
	else {
		// unmatched item, fail
		AVB_LOGF_ERROR("Unrecognized configuration item: section=%s, name=%s", section, name);
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return 0;
	}

	if (!valOK) {
		cfgValErr(section, name, value);
		AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
		return 0;
	}

	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return 1; // OK
}