Ejemplo n.º 1
0
static void* avdeccServerThread(void *arg)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	while (avdeccRunning) {
		if (!openavbAvdeccInitialize()) {
			AVB_LOG_ERROR("Failed to initialize AVDECC");
			break;
		}

		AVB_LOG_DEBUG("AVDECC Initialized");

		if (!openavbAvdeccStart()) {
			AVB_LOG_ERROR("Failed to start AVDECC");
			openavbAvdeccStop();
			break;
		}

		if (!openavbAvdeccMsgServerOpen()) {
			AVB_LOG_ERROR("Failed to start AVDECC Server");
			openavbAvdeccStop();
			break;
		}
		else {
			AVB_LOG_INFO("AVDECC Started");
			avdeccInitSucceeded = TRUE;

			// Wait until AVDECC is finished.
			while (avdeccRunning) {
				openavbAvdeccMsgSrvrService();
			}

			openavbAvdeccMsgServerClose();
		}

		// Stop AVDECC
		AVB_LOG_DEBUG("AVDECC Stopping");
		openavbAvdeccStop();
		AVB_LOG_INFO("AVDECC Stopped");
	}

	// Shutdown AVDECC
	openavbAvdeccCleanup();

	avdeccRunning = FALSE;

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return NULL;
}
openavbAvdeccMsgStateType_t openavbAVDECCGetStreamingState(openavb_aem_descriptor_stream_io_t *pDescriptorStream, U16 configIdx)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	// Sanity tests.
	if (!pDescriptorStream) {
		AVB_LOG_ERROR("openavbAVDECCGetStreamingState Invalid descriptor");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return OPENAVB_AVDECC_MSG_UNKNOWN;
	}
	if (!pDescriptorStream->stream) {
		AVB_LOG_ERROR("openavbAVDECCGetStreamingState Invalid descriptor stream");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return OPENAVB_AVDECC_MSG_UNKNOWN;
	}
	if (!pDescriptorStream->stream->client) {
		AVB_LOG_DEBUG("openavbAVDECCGetStreamingState Invalid stream client pointer");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return OPENAVB_AVDECC_MSG_UNKNOWN;
	}

	// Return the current state.
	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
	return pDescriptorStream->stream->client->lastReportedState;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
static bool openavbAvdeccMsgSrvrReceiveFromClient(int avdeccMsgHandle, openavbAvdeccMessage_t *msg)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC_MSG);

	if (!msg) {
		AVB_LOG_ERROR("Receiving message; invalid argument passed");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
		return FALSE;
	}

	bool ret = FALSE;
	switch (msg->type) {
		case OPENAVB_AVDECC_MSG_VERSION_REQUEST:
			AVB_LOG_DEBUG("Message received:  OPENAVB_AVDECC_MSG_VERSION_REQUEST");
			ret = openavbAvdeccMsgSrvrHndlVerRqstFromClient(avdeccMsgHandle);
			break;
		case OPENAVB_AVDECC_MSG_CLIENT_INIT_IDENTIFY:
			AVB_LOG_DEBUG("Message received:  OPENAVB_AVDECC_MSG_CLIENT_INIT_IDENTIFY");
			ret = openavbAvdeccMsgSrvrHndlInitIdentifyFromClient(avdeccMsgHandle,
				msg->params.clientInitIdentify.friendly_name,
				msg->params.clientInitIdentify.talker);
			break;
		case OPENAVB_AVDECC_MSG_C2S_TALKER_STREAM_ID:
			AVB_LOG_DEBUG("Message received:  OPENAVB_AVDECC_MSG_C2S_TALKER_STREAM_ID");
			ret = openavbAvdeccMsgSrvrHndlTalkerStreamIDFromClient(avdeccMsgHandle,
				msg->params.c2sTalkerStreamID.sr_class,
				msg->params.c2sTalkerStreamID.stream_src_mac,
				ntohs(msg->params.c2sTalkerStreamID.stream_uid),
				msg->params.c2sTalkerStreamID.stream_dest_mac,
				ntohs(msg->params.c2sTalkerStreamID.stream_vlan_id));
			break;
		case OPENAVB_AVDECC_MSG_CLIENT_CHANGE_NOTIFICATION:
			AVB_LOG_DEBUG("Message received:  OPENAVB_AVDECC_MSG_CLIENT_CHANGE_NOTIFICATION");
			ret = openavbAvdeccMsgSrvrHndlChangeNotificationFromClient(avdeccMsgHandle, (openavbAvdeccMsgStateType_t) msg->params.clientChangeNotification.current_state);
			break;
		default:
			AVB_LOG_ERROR("Unexpected message received at server");
			break;
	}

	AVB_LOGF_VERBOSE("Message handled, ret=%d", ret);
	AVB_TRACE_EXIT(AVB_TRACE_AVDECC_MSG);
	return ret;
}
Ejemplo n.º 5
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;
}
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;
}
Ejemplo 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;
}
Ejemplo n.º 8
0
/***********************************************
 * Signal handler - used to respond to signals.
 * Allows graceful cleanup.
 */
static void openavbTLSigHandler(int signal)
{
	AVB_TRACE_ENTRY(AVB_TRACE_HOST);

	if (signal == SIGINT) {
		AVB_LOG_INFO("Host shutting down");
		bRunning = FALSE;
	}
	else if (signal == SIGUSR1) {
		AVB_LOG_DEBUG("Waking up streaming thread");
	}
	else {
		AVB_LOG_ERROR("Unexpected signal");
	}

	AVB_TRACE_EXIT(AVB_TRACE_HOST);
}
Ejemplo n.º 9
0
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;
}
void openavbAVDECCPauseStream(openavb_aem_descriptor_stream_io_t *pDescriptor, bool bPause)
{
	AVB_TRACE_ENTRY(AVB_TRACE_AVDECC);

	// Sanity test.
	if (!pDescriptor) {
		AVB_LOG_ERROR("openavbAVDECCPauseStream Invalid descriptor");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return;
	}
	if (!pDescriptor->stream) {
		AVB_LOG_ERROR("openavbAVDECCPauseStream Invalid StreamInput descriptor stream");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return;
	}
	if (!pDescriptor->stream->client) {
		AVB_LOG_ERROR("openavbAVDECCPauseStream Invalid stream client pointer");
		AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
		return;
	}

	if (pDescriptor->descriptor_type == OPENAVB_AEM_DESCRIPTOR_STREAM_INPUT) {

		if (bPause) {
			// If the client is not running (or already paused), ignore this command.
			if (pDescriptor->stream->client->lastReportedState != OPENAVB_AVDECC_MSG_RUNNING) {
				AVB_LOG_DEBUG("Listener state change to pause ignored, as Listener not running");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			// Send the request to the client.
			if (!openavbAvdeccMsgSrvrChangeRequest(pDescriptor->stream->client->avdeccMsgHandle, OPENAVB_AVDECC_MSG_PAUSED)) {
				AVB_LOG_ERROR("Error requesting Listener change to Paused");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			AVB_LOG_INFO("Listener state change from Running to Paused requested");
		}
		else {
			// If the client is not paused, ignore this command.
			if (pDescriptor->stream->client->lastReportedState != OPENAVB_AVDECC_MSG_PAUSED) {
				AVB_LOG_DEBUG("Listener state change to pause ignored, as Listener not paused");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			// Send the request to the client.
			if (!openavbAvdeccMsgSrvrChangeRequest(pDescriptor->stream->client->avdeccMsgHandle, OPENAVB_AVDECC_MSG_RUNNING)) {
				AVB_LOG_ERROR("Error requesting Listener change to Running");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			AVB_LOG_INFO("Listener state change from Paused to Running requested");
		}
	}
	else if (pDescriptor->descriptor_type == OPENAVB_AEM_DESCRIPTOR_STREAM_OUTPUT) {

		if (bPause) {
			// If the client is not running (or already paused), ignore this command.
			if (pDescriptor->stream->client->lastReportedState != OPENAVB_AVDECC_MSG_RUNNING) {
				AVB_LOG_DEBUG("Talker state change to pause ignored, as Talker not running");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			// Send the request to the client.
			if (!openavbAvdeccMsgSrvrChangeRequest(pDescriptor->stream->client->avdeccMsgHandle, OPENAVB_AVDECC_MSG_PAUSED)) {
				AVB_LOG_ERROR("Error requesting Talker change to Paused");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			AVB_LOG_INFO("Talker state change from Running to Paused requested");
		}
		else {
			// If the client is not paused, ignore this command.
			if (pDescriptor->stream->client->lastReportedState != OPENAVB_AVDECC_MSG_PAUSED) {
				AVB_LOG_DEBUG("Talker state change to pause ignored, as Talker not paused");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			// Send the request to the client.
			if (!openavbAvdeccMsgSrvrChangeRequest(pDescriptor->stream->client->avdeccMsgHandle, OPENAVB_AVDECC_MSG_RUNNING)) {
				AVB_LOG_ERROR("Error requesting Talker change to Running");
				AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
				return;
			}

			AVB_LOG_INFO("Talker state change from Paused to Running requested");
		}
	}
	else {
		AVB_LOG_ERROR("openavbAVDECCPauseStream unsupported descriptor");
	}

	AVB_TRACE_EXIT(AVB_TRACE_AVDECC);
}
Ejemplo n.º 11
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;
}
/* 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);
}
Ejemplo n.º 13
0
void openavbAcmpSMControllerStateMachine()
{
	AVB_TRACE_ENTRY(AVB_TRACE_ACMP);

	openavb_acmp_InflightCommand_t *pInflightActive = NULL;		// The inflight command for the current state
	openavb_acmp_sm_controller_state_t state = OPENAVB_ACMP_SM_CONTROLLER_STATE_WAITING;

	// Lock such that the mutex is held unless waiting for a semaphore. Synchronous processing of command responses.
	ACMP_SM_LOCK();
	while (bRunning) {
		switch (state) {
			case OPENAVB_ACMP_SM_CONTROLLER_STATE_WAITING:
				AVB_TRACE_LINE(AVB_TRACE_ACMP);
				AVB_LOG_DEBUG("State:  OPENAVB_ACMP_SM_CONTROLLER_STATE_WAITING");

				openavbAcmpSMControllerVars.rcvdResponse = FALSE;

				// Calculate timeout for inflight commands
				// Start is a arbitrary large time out.
				struct timespec timeout;
				CLOCK_GETTIME(OPENAVB_CLOCK_REALTIME, &timeout);
				timeout.tv_sec += 60;	// At most will timeout after 60 seconds

				// Look for soonest inflight command timeout
				openavb_list_node_t node = openavbListIterFirst(openavbAcmpSMControllerVars.inflight);
				while (node) {
					openavb_acmp_InflightCommand_t *pInflight = openavbListData(node);
					if ((openavbTimeTimespecCmp(&pInflight->timer, &timeout) < 0)) {
						timeout.tv_sec = pInflight->timer.tv_sec;
						timeout.tv_nsec = pInflight->timer.tv_nsec;
					}
					node = openavbListIterNext(openavbAcmpSMControllerVars.inflight);
				}

				ACMP_SM_UNLOCK();
				U32 timeoutMSec = 0;
				struct timespec now;
				CLOCK_GETTIME(OPENAVB_CLOCK_REALTIME, &now);
				timeoutMSec = openavbTimeUntilMSec(&now, &timeout);
				SEM_ERR_T(err);
				SEM_TIMEDWAIT(openavbAcmpSMControllerSemaphore, timeoutMSec, err);
				ACMP_SM_LOCK();

				if (!SEM_IS_ERR_NONE(err)) {
					if (SEM_IS_ERR_TIMEOUT(err)) {
						struct timespec now;
						CLOCK_GETTIME(OPENAVB_CLOCK_REALTIME, &now);

						// Look for a timed out inflight command
						openavb_list_node_t node = openavbListIterFirst(openavbAcmpSMControllerVars.inflight);
						while (node) {
							openavb_acmp_InflightCommand_t *pInflight = openavbListData(node);
							if ((openavbTimeTimespecCmp(&now, &pInflight->timer) >= 0)) {
								// Found a timed out command
								state = OPENAVB_ACMP_SM_CONTROLLER_STATE_TIMEOUT;
								pInflightActive = pInflight;
								break;
							}
							node = openavbListIterNext(openavbAcmpSMControllerVars.inflight);
						}
					}
				}
				else {
					if (openavbAcmpSMControllerVars.doTerminate) {
						bRunning = FALSE;
					}
					else if (openavbAcmpSMControllerVars.rcvdResponse &&
							memcmp(pRcvdCmdResp->controller_entity_id, openavbAcmpSMGlobalVars.my_id, sizeof(openavbAcmpSMGlobalVars.my_id)) == 0) {
						// Look for a corresponding inflight command
						openavb_list_node_t node = openavbListIterFirst(openavbAcmpSMControllerVars.inflight);
						while (node) {
							openavb_acmp_InflightCommand_t *pInflight = openavbListData(node);
							if (pRcvdCmdResp->sequence_id == pInflight->command.sequence_id &&
									pRcvdCmdResp->message_type == pInflight->command.message_type + 1) {
								// Found a corresponding command
								state = OPENAVB_ACMP_SM_CONTROLLER_STATE_RESPONSE;
								pInflightActive = pInflight;
								break;
							}
							node = openavbListIterNext(openavbAcmpSMControllerVars.inflight);
						}
					}
				break;

			case OPENAVB_ACMP_SM_CONTROLLER_STATE_TIMEOUT:
				{
					AVB_TRACE_LINE(AVB_TRACE_ACMP);
					AVB_LOG_DEBUG("State:  OPENAVB_ACMP_SM_CONTROLLER_STATE_TIMEOUT");

					if (pInflightActive) {
						if (pInflightActive->retried) {
							openavbAcmpSMController_removeInflight(&pInflightActive->command);
						}
						else {
							openavbAcmpSMController_txCommand(pInflightActive->command.message_type, &pInflightActive->command, TRUE);
						}
					}
					pInflightActive = NULL;
					state = OPENAVB_ACMP_SM_CONTROLLER_STATE_WAITING;
				}
				break;

			case OPENAVB_ACMP_SM_CONTROLLER_STATE_RESPONSE:
				{
					AVB_TRACE_LINE(AVB_TRACE_ACMP);
					AVB_LOG_DEBUG("State:  OPENAVB_ACMP_SM_CONTROLLER_STATE_RESPONSE");

					if (pInflightActive) {
						openavbAcmpSMController_cancelTimeout(pRcvdCmdResp);
						openavbAcmpSMController_processResponse(pRcvdCmdResp);
						openavbAcmpSMController_removeInflight(pRcvdCmdResp);
					}
					pInflightActive = NULL;
					state = OPENAVB_ACMP_SM_CONTROLLER_STATE_WAITING;
				}
				break;
			}
		}
	}
	ACMP_SM_UNLOCK();

	AVB_TRACE_EXIT(AVB_TRACE_ACMP);
}
Ejemplo n.º 14
0
/* SRP tells us about a listener peer (Listener Ready or Failed)
 */
openavbRC strmAttachCb(void* pv,
							 openavbSrpLsnrDeclSubtype_t lsnrDecl)
{
	AVB_TRACE_ENTRY(AVB_TRACE_ENDPOINT);

	openavbRC rc = OPENAVB_FAILURE;
	clientStream_t *ps = (clientStream_t*)pv;

	AVB_LOGF_INFO("SRP talker callback uid=%d: lsnrDecl=%x", ps->streamID.uniqueID, lsnrDecl);

	if (lsnrDecl == openavbSrp_LDSt_Ready
		|| lsnrDecl == openavbSrp_LDSt_Ready_Failed)
	{
		// Somebody is listening - get ready to stream

		if (ps->fwmark != INVALID_FWMARK) {
			AVB_LOG_DEBUG("attach callback: already setup queues");
			rc = OPENAVB_SUCCESS;
		}
		else {
			AVB_LOG_DEBUG("Attach callback: setting up queues for streaming");

			rc = openavbSrpGetClassParams(ps->srClass, &ps->priority, &ps->vlanID, &ps->classRate);
			if (IS_OPENAVB_SUCCESS(rc)) {
				ps->fwmark = openavbQmgrAddStream(ps->srClass, ps->classRate, ps->tSpec.maxIntervalFrames, ps->tSpec.maxFrameSize);
				if (ps->fwmark == INVALID_FWMARK) {
					AVB_LOG_ERROR("Error in attach callback: unable to setup stream queues");
					rc = OPENAVB_FAILURE;
				}
				else {
					rc = OPENAVB_SUCCESS;
				}
			}
			else {
				AVB_LOG_ERROR("Error in attach callback: unable to get class params");
				rc = OPENAVB_FAILURE;
			}
		}
	}
	else {
		// Nobody listening
		if (ps->fwmark != INVALID_FWMARK) {
			AVB_LOG_DEBUG("Attach callback: tearing down queues");
			openavbQmgrRemoveStream(ps->fwmark);
			ps->fwmark = INVALID_FWMARK;
		}
		rc = OPENAVB_SUCCESS;
	}

	if (IS_OPENAVB_SUCCESS(rc)) {

		openavbEptSrvrNotifyTlkrOfSrpCb(ps->clientHandle,
		                             &ps->streamID,
		                             x_cfg.ifname,
		                             ps->destAddr,
		                             lsnrDecl,
		                             ps->srClass,
		                             ps->classRate,
		                             ps->vlanID,
		                             ps->priority,
		                             ps->fwmark);
		rc = OPENAVB_SUCCESS;
	}

	AVB_TRACE_EXIT(AVB_TRACE_ENDPOINT);
	return rc;
}