Example #1
0
static int set_clock_info(struct ctrl_cmd *cmd, void *data)
{
	struct gsm_bts_trx *trx = cmd->node;
	struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
	struct msgb *msg = sysp_msgb_alloc();
	SuperFemto_Prim_t *sysp = msgb_sysprim(msg);
	struct ctrl_cmd_def *cd;

	/* geneate a deferred control command */
	cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10);

	/* Set GPS/PPS as reference */
	sysp->id = SuperFemto_PrimId_RfClockSetupReq;
	sysp->u.rfClockSetupReq.rfTrx.iClkCor = fl1h->clk_cal; /* !!! use get_clk_cal */
	sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src;
	sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps;
	l1if_req_compl(fl1h, msg, clock_setup_cb, NULL);

	/* Reset the error counters */
	msg = sysp_msgb_alloc();
	sysp = msgb_sysprim(msg);
	sysp->id = SuperFemto_PrimId_RfClockInfoReq;
	sysp->u.rfClockInfoReq.u8RstClkCal = 1;

	l1if_req_compl(fl1h, msg, ctrl_set_clkinfo_cb, cd);

	return CTRL_CMD_HANDLED;
}
Example #2
0
static int get_clock_info(struct ctrl_cmd *cmd, void *data)
{
	struct gsm_bts_trx *trx = cmd->node;
	struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
	struct msgb *msg = sysp_msgb_alloc();
	SuperFemto_Prim_t *sysp = msgb_sysprim(msg);
	struct ctrl_cmd_def *cd;

	/* geneate a deferred control command */
	cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10);

	sysp->id = SuperFemto_PrimId_RfClockInfoReq;
	sysp->u.rfClockInfoReq.u8RstClkCal = 0;

	return l1if_req_compl(fl1h, msg, ctrl_clkinfo_cb, cd);
}
Example #3
0
static int ctrl_get_clkcorr_cb(struct gsm_bts_trx *trx, struct msgb *resp,
				void *data)
{
	SuperFemto_Prim_t *sysp = msgb_sysprim(resp);
	struct ctrl_cmd_def *cd = data;
	struct ctrl_cmd *cmd = cd->cmd;

	if (ctrl_cmd_def_is_zombie(cd)) {
		msgb_free(resp);
		return 0;
	}

	cmd->reply = talloc_asprintf(cmd, "%d",
		sysp->u.rfClockInfoCnf.rfTrx.iClkCor);

	ctrl_cmd_def_send(cd);

	msgb_free(resp);

	return 0;
}
Example #4
0
static int set_clock_corr(struct ctrl_cmd *cmd, void *data)
{
	struct gsm_bts_trx *trx = cmd->node;
	struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
	struct msgb *msg = sysp_msgb_alloc();
	SuperFemto_Prim_t *sysp = msgb_sysprim(msg);
	struct ctrl_cmd_def *cd;

	fl1h->clk_cal = atoi(cmd->value);

	/* geneate a deferred control command */
	cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10);

	sysp->id = SuperFemto_PrimId_RfClockSetupReq;
	sysp->u.rfClockSetupReq.rfTrx.iClkCor = fl1h->clk_cal;
	sysp->u.rfClockSetupReq.rfTrx.clkSrc = fl1h->clk_src;
	sysp->u.rfClockSetupReq.rfTrxClkCal.clkSrc = SuperFemto_ClkSrcId_GpsPps;

	l1if_req_compl(fl1h, msg, ctrl_set_clkcorr_cb, cd);

	return CTRL_CMD_HANDLED;
}
Example #5
0
static int get_clock_corr(struct ctrl_cmd *cmd, void *data)
{
	struct gsm_bts_trx *trx = cmd->node;
	struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
	struct msgb *msg = sysp_msgb_alloc();
	SuperFemto_Prim_t *sysp = msgb_sysprim(msg);
	struct ctrl_cmd_def *cd;

	/* we could theoretically simply respond with a cached value, but I
	 * prefer to to ask the actual L1 about the currently used value to
	 * avoid any mistakes */

	/* geneate a deferred control command */
	cd = ctrl_cmd_def_make(fl1h, cmd, NULL, 10);

	sysp->id = SuperFemto_PrimId_RfClockInfoReq;
	sysp->u.rfClockInfoReq.u8RstClkCal = 0;

	l1if_req_compl(fl1h, msg, ctrl_get_clkcorr_cb, cd);

	return CTRL_CMD_HANDLED;
}
Example #6
0
static int ctrl_clkinfo_cb(struct gsm_bts_trx *trx, struct msgb *resp,
			   void *data)
{
	SuperFemto_Prim_t *sysp = msgb_sysprim(resp);
	struct ctrl_cmd_def *cd = data;
	struct ctrl_cmd *cmd = cd->cmd;

	LOGP(DL1C, LOGL_NOTICE,
		"RfClockInfo iClkCor=%d/clkSrc=%s Err=%d/ErrRes=%d/clkSrc=%s\n",
		sysp->u.rfClockInfoCnf.rfTrx.iClkCor,
		get_value_string(femtobts_clksrc_names,
				sysp->u.rfClockInfoCnf.rfTrx.clkSrc),
		sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr,
		sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes,
		get_value_string(femtobts_clksrc_names,
				sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc));

	if (ctrl_cmd_def_is_zombie(cd)) {
		msgb_free(resp);
		return 0;
	}

	cmd->reply = talloc_asprintf(cmd, "%d,%s,%d,%d,%s",
		sysp->u.rfClockInfoCnf.rfTrx.iClkCor,
		get_value_string(femtobts_clksrc_names,
				sysp->u.rfClockInfoCnf.rfTrx.clkSrc),
		sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErr,
		sysp->u.rfClockInfoCnf.rfTrxClkCal.iClkErrRes,
		get_value_string(femtobts_clksrc_names,
				sysp->u.rfClockInfoCnf.rfTrxClkCal.clkSrc));

	ctrl_cmd_def_send(cd);

	msgb_free(resp);

	return 0;
}
Example #7
0
static int ctrl_set_clkcorr_cb(struct gsm_bts_trx *trx, struct msgb *resp,
				void *data)
{
	SuperFemto_Prim_t *sysp = msgb_sysprim(resp);
	struct ctrl_cmd_def *cd = data;
	struct ctrl_cmd *cmd = cd->cmd;

	if (ctrl_cmd_def_is_zombie(cd)) {
		msgb_free(resp);
		return 0;
	}

	if (sysp->u.rfClockSetupCnf.status != GsmL1_Status_Success) {
		cmd->type = CTRL_CMD_ERROR;
		cmd->reply = "Error setting new correction value.";
	} else
		cmd->reply = "success";

	ctrl_cmd_def_send(cd);

	msgb_free(resp);

	return 0;
}
Example #8
0
static int _l1if_req_compl(struct lc15l1_hdl *fl1h, struct msgb *msg,
		   int is_system_prim, l1if_compl_cb *cb, void *data)
{
	struct wait_l1_conf *wlc;
	struct osmo_wqueue *wqueue;
	unsigned int timeout_secs;

	/* allocate new wsc and store reference to mutex and conf_id */
	wlc = talloc_zero(fl1h, struct wait_l1_conf);
	wlc->cb = cb;
	wlc->cb_data = data;

	/* Make sure we actually have received a REQUEST type primitive */
	if (is_system_prim == 0) {
		GsmL1_Prim_t *l1p = msgb_l1prim(msg);

		LOGP(DL1P, LOGL_INFO, "Tx L1 prim %s\n",
			get_value_string(lc15bts_l1prim_names, l1p->id));

		if (lc15bts_get_l1prim_type(l1p->id) != L1P_T_REQ) {
			LOGP(DL1C, LOGL_ERROR, "L1 Prim %s is not a Request!\n",
				get_value_string(lc15bts_l1prim_names, l1p->id));
			talloc_free(wlc);
			return -EINVAL;
		}
		wlc->is_sys_prim = 0;
		wlc->conf_prim_id = lc15bts_get_l1prim_conf(l1p->id);
		wlc->conf_hLayer3 = l1p_get_hLayer3(l1p);
		wqueue = &fl1h->write_q[MQ_L1_WRITE];
		timeout_secs = 30;
	} else {
		Litecell15_Prim_t *sysp = msgb_sysprim(msg);

		LOGP(DL1C, LOGL_INFO, "Tx SYS prim %s\n",
			get_value_string(lc15bts_sysprim_names, sysp->id));

		if (lc15bts_get_sysprim_type(sysp->id) != L1P_T_REQ) {
			LOGP(DL1C, LOGL_ERROR, "SYS Prim %s is not a Request!\n",
				get_value_string(lc15bts_sysprim_names, sysp->id));
			talloc_free(wlc);
			return -EINVAL;
		}
		wlc->is_sys_prim = 1;
		wlc->conf_prim_id = lc15bts_get_sysprim_conf(sysp->id);
		wqueue = &fl1h->write_q[MQ_SYS_WRITE];
		timeout_secs = 30;
	}

	/* enqueue the message in the queue and add wsc to list */
	if (osmo_wqueue_enqueue(wqueue, msg) != 0) {
		/* So we will get a timeout but the log message might help */
		LOGP(DL1C, LOGL_ERROR, "Write queue for %s full. dropping msg.\n",
			is_system_prim ? "system primitive" : "gsm");
		msgb_free(msg);
	}
	llist_add(&wlc->list, &fl1h->wlc_list);

	/* schedule a timer for timeout_secs seconds. If DSP fails to respond, we terminate */
	wlc->timer.data = wlc;
	wlc->timer.cb = l1if_req_timeout;
	osmo_timer_schedule(&wlc->timer, timeout_secs, 0);

	return 0;
}