summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <axilirator@gmail.com>2017-07-15 15:20:35 +0700
committerVadim Yanitskiy <axilirator@gmail.com>2017-10-23 22:05:49 +0330
commit55040a29a8eef6adde1a9f6ea5f977672b513814 (patch)
tree5399d948261870048fcd749a29a4bee48fd94e21
parentf7da2a39bb2f86e1de052cd2f6b6ae8e748a93f6 (diff)
host/trxcon/l1ctl.c: handle L1CTL_DM_{EST,REL}_REQ
-rw-r--r--src/host/trxcon/l1ctl.c92
-rw-r--r--src/host/trxcon/sched_trx.c48
-rw-r--r--src/host/trxcon/sched_trx.h3
-rw-r--r--src/host/trxcon/trx_if.h1
4 files changed, 144 insertions, 0 deletions
diff --git a/src/host/trxcon/l1ctl.c b/src/host/trxcon/l1ctl.c
index 3098d9c6..34e4b3c2 100644
--- a/src/host/trxcon/l1ctl.c
+++ b/src/host/trxcon/l1ctl.c
@@ -470,6 +470,94 @@ exit:
return rc;
}
+static int l1ctl_rx_dm_est_req(struct l1ctl_link *l1l, struct msgb *msg)
+{
+ enum gsm_phys_chan_config config;
+ enum trx_lchan_type lchan_type;
+ struct l1ctl_dm_est_req *est_req;
+ struct l1ctl_info_ul *ul;
+ struct trx_ts *ts;
+ uint16_t band_arfcn;
+ uint8_t chan_nr, tn;
+ int rc = 0;
+
+ ul = (struct l1ctl_info_ul *) msg->l1h;
+ est_req = (struct l1ctl_dm_est_req *) ul->payload;
+
+ band_arfcn = ntohs(est_req->h0.band_arfcn);
+ chan_nr = ul->chan_nr;
+
+ LOGP(DL1C, LOGL_DEBUG, "Recv L1CTL_DM_EST_REQ (arfcn=%u, "
+ "chan_nr=0x%02x, tsc=%u)\n", (band_arfcn &~ ARFCN_FLAG_MASK),
+ chan_nr, est_req->tsc);
+
+ if (est_req->h) {
+ LOGP(DL1C, LOGL_ERROR, "FHSS is not supported\n");
+ rc = -ENOTSUP;
+ goto exit;
+ }
+
+ /* Update TSC (Training Sequence) */
+ /* FIXME: est_req->tsc is a number of TSC */
+ memset(l1l->trx->tsc, 0x00, 26);
+
+ /* Determine channel config */
+ config = sched_trx_chan_nr2pchan_config(chan_nr);
+ if (config == GSM_PCHAN_NONE) {
+ LOGP(DL1C, LOGL_ERROR, "Couldn't determine channel config\n");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Determine TS index */
+ tn = chan_nr & 0x7;
+ if (tn > 7) {
+ LOGP(DL1C, LOGL_ERROR, "Incorrect TS index %u\n", tn);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Determine lchan type */
+ lchan_type = sched_trx_chan_nr2lchan_type(chan_nr);
+ if (!lchan_type) {
+ LOGP(DL1C, LOGL_ERROR, "Couldn't determine lchan type\n");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Configure requested TS */
+ rc = sched_trx_configure_ts(l1l->trx, tn, config);
+ if (rc) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Find just configured TS */
+ ts = sched_trx_find_ts(l1l->trx, tn);
+
+ /* Activate only requested lchan, disabling others */
+ sched_trx_deactivate_all_lchans(ts);
+ rc = sched_trx_activate_lchan(ts, lchan_type);
+ if (rc) {
+ LOGP(DL1C, LOGL_ERROR, "Couldn't activate lchan\n");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ msgb_free(msg);
+ return rc;
+}
+
+static int l1ctl_rx_dm_rel_req(struct l1ctl_link *l1l, struct msgb *msg)
+{
+ /* Reset scheduler */
+ sched_trx_reset(l1l->trx);
+
+ msgb_free(msg);
+ return 0;
+}
+
int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg)
{
struct l1ctl_hdr *l1h;
@@ -490,6 +578,10 @@ int l1ctl_rx_cb(struct l1ctl_link *l1l, struct msgb *msg)
return l1ctl_rx_ccch_mode_req(l1l, msg);
case L1CTL_RACH_REQ:
return l1ctl_rx_rach_req(l1l, msg);
+ case L1CTL_DM_EST_REQ:
+ return l1ctl_rx_dm_est_req(l1l, msg);
+ case L1CTL_DM_REL_REQ:
+ return l1ctl_rx_dm_rel_req(l1l, msg);
default:
LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type);
msgb_free(msg);
diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c
index 1effeb7c..be7a480d 100644
--- a/src/host/trxcon/sched_trx.c
+++ b/src/host/trxcon/sched_trx.c
@@ -372,6 +372,54 @@ int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan)
return 0;
}
+void sched_trx_deactivate_all_lchans(struct trx_ts *ts)
+{
+ struct trx_lchan_state *lchan;
+ int i, len;
+
+ len = talloc_array_length(ts->lchans);
+ for (i = 0; i < len; i++) {
+ lchan = ts->lchans + i;
+
+ talloc_free(lchan->rx_bursts);
+ talloc_free(lchan->tx_bursts);
+
+ lchan->active = 0;
+ }
+}
+
+enum gsm_phys_chan_config sched_trx_chan_nr2pchan_config(uint8_t chan_nr)
+{
+ uint8_t cbits = chan_nr >> 3;
+
+ if (cbits == 0x01)
+ return GSM_PCHAN_TCH_F;
+ else if ((cbits & 0x1e) == 0x02)
+ return GSM_PCHAN_TCH_H;
+ else if ((cbits & 0x1c) == 0x04)
+ return GSM_PCHAN_CCCH_SDCCH4;
+ else if ((cbits & 0x18) == 0x08)
+ return GSM_PCHAN_SDCCH8_SACCH8C;
+
+ return GSM_PCHAN_NONE;
+}
+
+enum trx_lchan_type sched_trx_chan_nr2lchan_type(uint8_t chan_nr)
+{
+ uint8_t cbits = chan_nr >> 3;
+
+ if (cbits == 0x01)
+ return TRXC_TCHF;
+ else if ((cbits & 0x1e) == 0x02)
+ return TRXC_TCHH_0 + (cbits & 0x1);
+ else if ((cbits & 0x1c) == 0x04)
+ return TRXC_SDCCH4_0 + (cbits & 0x3);
+ else if ((cbits & 0x18) == 0x08)
+ return TRXC_SDCCH8_0 + (cbits & 0x7);
+
+ return TRXC_IDLE;
+}
+
int sched_trx_handle_rx_burst(struct trx_instance *trx, uint8_t ts_num,
uint32_t burst_fn, sbit_t *bits, uint16_t nbits, int8_t rssi, float toa)
{
diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h
index 809a3243..725f666d 100644
--- a/src/host/trxcon/sched_trx.h
+++ b/src/host/trxcon/sched_trx.h
@@ -258,6 +258,9 @@ int sched_trx_configure_ts(struct trx_instance *trx, int ts_num,
enum gsm_phys_chan_config config);
/* Logical channel management functions */
+enum gsm_phys_chan_config sched_trx_chan_nr2pchan_config(uint8_t chan_nr);
+enum trx_lchan_type sched_trx_chan_nr2lchan_type(uint8_t chan_nr);
+void sched_trx_deactivate_all_lchans(struct trx_ts *ts);
int sched_trx_activate_lchan(struct trx_ts *ts, enum trx_lchan_type chan);
int sched_trx_deactivate_lchan(struct trx_ts *ts, enum trx_lchan_type chan);
struct trx_lchan_state *sched_trx_find_lchan(struct trx_ts *ts,
diff --git a/src/host/trxcon/trx_if.h b/src/host/trxcon/trx_if.h
index 8ba09b8a..9e3a32a2 100644
--- a/src/host/trxcon/trx_if.h
+++ b/src/host/trxcon/trx_if.h
@@ -32,6 +32,7 @@ struct trx_instance {
uint16_t pm_arfcn_start;
uint16_t pm_arfcn_stop;
uint16_t band_arfcn;
+ uint8_t tsc[26];
uint8_t bsic;
/* Scheduler stuff */