Exemplo n.º 1
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
}
Exemplo n.º 2
0
EXTERN_DLL_EXPORT bool openavbTLConfigure(tl_handle_t handle, openavb_tl_cfg_t *pCfgIn, openavb_tl_cfg_name_value_t *pNVCfg)
{
	AVB_TRACE_ENTRY(AVB_TRACE_TL);

	tl_state_t *pTLState = (tl_state_t *)handle;

	if (!pTLState) {
		AVB_LOG_ERROR("Invalid handle.");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return FALSE;
	}

	// Create the mediaQ
	pTLState->pMediaQ = openavbMediaQCreate();
	if (!pTLState->pMediaQ) {
		AVB_LOG_ERROR("Unable to create media queue");
		AVB_TRACE_EXIT(AVB_TRACE_TL);
		return FALSE;
	}

	// CORE_TODO: It's not safe to simply copy the openavb_tl_cfg_t since there are embedded pointers in the cfg_mac_t member.
	// Those pointers need to be updated after a copy. Longer term the cfg_mac_t should be changed to not contain the mac
	// member to remedy this issue and avoid further bugs.
	memcpy(&pTLState->cfg, pCfgIn, sizeof(openavb_tl_cfg_t));
	pTLState->cfg.dest_addr.mac = &pTLState->cfg.dest_addr.buffer;
	pTLState->cfg.stream_addr.mac = &pTLState->cfg.stream_addr.buffer;

	openavb_tl_cfg_t *pCfg = &pTLState->cfg;

	if (!((pCfg->role == AVB_ROLE_TALKER) || (pCfg->role == AVB_ROLE_LISTENER))) {
		AVB_LOG_ERROR("Talker - Listener Config Error: invalid role");
		return FALSE;
	}

	if ((pCfg->role == AVB_ROLE_TALKER) && (pCfg->max_interval_frames == 0)) {
		AVB_LOG_ERROR("Talker - Listener Config Error: talker role requires 'max_interval_frames'");
		return FALSE;
	}

	openavbMediaQSetMaxStaleTail(pTLState->pMediaQ, pCfg->max_stale);

	if (!openavbTLOpenLinkLibsOsal(pTLState)) {
		AVB_LOG_ERROR("Failed to open mapping / interface library");
		return FALSE;
	}

	if (pCfg->pMapInitFn && pCfg->pMapInitFn(pTLState->pMediaQ, &pCfg->map_cb, pCfg->max_transit_usec)) {
		checkMapCallbacks(&pTLState->cfg);
	}
	else {
		AVB_LOG_ERROR("Mapping initialize function error.");
		return FALSE;
	}

	if (pCfg->pIntfInitFn && pCfg->pIntfInitFn(pTLState->pMediaQ, &pCfg->intf_cb)) {
		checkIntfCallbacks(&pTLState->cfg);
	}
	else {
		AVB_LOG_ERROR("Interface initialize function error.");
		return FALSE;
	}

	// Submit configuration values to mapping and interface modules
	int i;
	for (i = 0; i < pNVCfg->nLibCfgItems; i++) {
		if (MATCH_LEFT(pNVCfg->libCfgNames[i], "intf_nv_", 8)) {
			if (pCfg->intf_cb.intf_cfg_cb) {
				pCfg->intf_cb.intf_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]);
			}
			else {
				AVB_LOGF_ERROR("No interface module cfg function; ignoring %s", pNVCfg->libCfgNames[i]);
			}
		}
		else if (MATCH_LEFT(pNVCfg->libCfgNames[i], "map_nv_", 7)) {
			if (pCfg->map_cb.map_cfg_cb) {
				pCfg->map_cb.map_cfg_cb(pTLState->pMediaQ, pNVCfg->libCfgNames[i], pNVCfg->libCfgValues[i]);
			}
			else {
				AVB_LOGF_ERROR("No mapping module cfg function; ignoring %s", pNVCfg->libCfgNames[i]);
			}
		}
		else {
			assert(0);
		}
	} // for loop ends

	pTLState->cfg.map_cb.map_gen_init_cb(pTLState->pMediaQ);
	pTLState->cfg.intf_cb.intf_gen_init_cb(pTLState->pMediaQ);

	return TRUE;
}