// Called from openavbTLThreadFn() which is started from openavbTLRun() void openavbTLRunTalker(tl_state_t *pTLState) { AVB_TRACE_ENTRY(AVB_TRACE_TL); if (!pTLState) { AVB_LOG_ERROR("Invalid TLState"); AVB_TRACE_EXIT(AVB_TRACE_TL); return; } pTLState->pPvtTalkerData = calloc(1, sizeof(talker_data_t)); if (!pTLState->pPvtTalkerData) { AVB_LOG_WARNING("Failed to allocate talker data."); return; } // Create Stats Mutex { MUTEX_ATTR_HANDLE(mta); MUTEX_ATTR_INIT(mta); MUTEX_ATTR_SET_TYPE(mta, MUTEX_ATTR_TYPE_DEFAULT); MUTEX_ATTR_SET_NAME(mta, "TLStatsMutex"); MUTEX_CREATE_ERR(); MUTEX_CREATE(pTLState->statsMutex, mta); MUTEX_LOG_ERR("Could not create/initialize 'TLStatsMutex' mutex"); } /* If using endpoint register talker, else register with tpsec */ pTLState->bConnected = openavbTLRunTalkerInit(pTLState); if (pTLState->bConnected) { bool bServiceIPC; // Do until we are stopped or loose connection to endpoint while (pTLState->bRunning && pTLState->bConnected) { // Talk (or just sleep if not streaming.) bServiceIPC = talkerDoStream(pTLState); // TalkerDoStream() returns TRUE once per second, // so that we can service our IPC at that low rate. if (bServiceIPC) { // Look for messages from endpoint. Don't block (timeout=0) if (!openavbEptClntService(pTLState->endpointHandle, 0)) { AVB_LOGF_WARNING("Lost connection to endpoint, will retry "STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID))); pTLState->bConnected = FALSE; pTLState->endpointHandle = 0; } } } // Stop streaming talkerStopStream(pTLState); { MUTEX_CREATE_ERR(); MUTEX_DESTROY(pTLState->statsMutex); // Destroy Stats Mutex MUTEX_LOG_ERR("Error destroying mutex"); } // withdraw our talker registration if (pTLState->bConnected) openavbEptClntStopStream(pTLState->endpointHandle, &(((talker_data_t *)pTLState->pPvtTalkerData)->streamID)); openavbTLRunTalkerFinish(pTLState); } else { AVB_LOGF_WARNING("Failed to connect to endpoint"STREAMID_FORMAT, STREAMID_ARGS(&(((talker_data_t *)pTLState->pPvtTalkerData)->streamID))); } if (pTLState->pPvtTalkerData) { free(pTLState->pPvtTalkerData); pTLState->pPvtTalkerData = NULL; } AVB_TRACE_EXIT(AVB_TRACE_TL); }
/* 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); }