Fixed CM SERVICE REQUEST message.
[osmocom-bb.git] / src / host / layer23 / src / l1ctl.c
index d6aa176..051b3d8 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <osmocom/l1ctl.h>
 #include <osmocom/osmocom_data.h>
+#include <osmocom/l1l2_interface.h>
 #include <osmocom/lapdm.h>
 #include <osmocom/logging.h>
 #include <osmocom/gsmtap_util.h>
@@ -64,30 +65,40 @@ static struct msgb *osmo_l1_alloc(uint8_t msg_type)
 }
 
 
-static int osmo_make_band_arfcn(struct osmocom_ms *ms)
+static int osmo_make_band_arfcn(struct osmocom_ms *ms, uint16_t arfcn)
 {
        /* TODO: Include the band */
-       return ms->arfcn;
+       return arfcn;
 }
 
-static int rx_l1_ccch_resp(struct osmocom_ms *ms, struct msgb *msg)
+static int rx_l1_fbsb_resp(struct osmocom_ms *ms, struct msgb *msg)
 {
        struct l1ctl_info_dl *dl;
-       struct l1ctl_sync_new_ccch_resp *sb;
+       struct l1ctl_fbsb_resp *sb;
        struct gsm_time tm;
 
-       if (msgb_l3len(msg) < sizeof(*sb)) {
-               LOGP(DL1C, LOGL_ERROR, "MSG too short for CCCH RESP: %u\n",
+       if (msgb_l3len(msg) < sizeof(*dl) + sizeof(*sb)) {
+               LOGP(DL1C, LOGL_ERROR, "FBSB RESP: MSG too short %u\n",
                        msgb_l3len(msg));
                return -1;
        }
 
        dl = (struct l1ctl_info_dl *) msg->l1h;
-       sb = (struct l1ctl_sync_new_ccch_resp *) dl->payload;
+       sb = (struct l1ctl_fbsb_resp *) dl->payload;
+
+       printf("snr=%04x, arfcn=%u result=%u\n", dl->snr, ntohs(dl->band_arfcn),
+               sb->result);
+
+       if (sb->result != 0) {
+               LOGP(DL1C, LOGL_ERROR, "FBSB RESP: result=%u\n", sb->result);
+               dispatch_signal(SS_L1CTL, S_L1CTL_FBSB_ERR, ms);
+               return 0;
+       }
 
        gsm_fn2gsmtime(&tm, ntohl(dl->frame_nr));
        DEBUGP(DL1C, "SCH: SNR: %u TDMA: (%.4u/%.2u/%.2u) bsic: %d\n",
                dl->snr, tm.t1, tm.t2, tm.t3, sb->bsic);
+       dispatch_signal(SS_L1CTL, S_L1CTL_FBSB_RESP, ms);
 
        return 0;
 }
@@ -132,6 +143,7 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
        if (msgb_l3len(msg) < sizeof(*ccch)) {
                LOGP(DL1C, LOGL_ERROR, "MSG too short Data Ind: %u\n",
                        msgb_l3len(msg));
+               msgb_free(msg);
                return -1;
        }
 
@@ -145,6 +157,12 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
                chan_nr2string(dl->chan_nr), tm.t1, tm.t2, tm.t3,
                hexdump(ccch->data, sizeof(ccch->data)));
 
+       if (dl->num_biterr) {
+               LOGP(DL1C, LOGL_NOTICE, "Dropping frame with %u bit errors\n",
+                       dl->num_biterr);
+               return 0;
+       }
+
        /* send CCCH data via GSMTAP */
        gsmtap_chan_type = chantype_rsl2gsmtap(chan_type, dl->link_id);
        gsmtap_sendmsg(dl->band_arfcn, chan_ts, gsmtap_chan_type, chan_ss,
@@ -213,18 +231,28 @@ int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
        return osmo_send_l1(ms, msg);
 }
 
-/* Transmit NEW_CCCH_REQ */
-int l1ctl_tx_ccch_req(struct osmocom_ms *ms)
+/* Transmit FBSB_REQ */
+int l1ctl_tx_fbsb_req(struct osmocom_ms *ms, uint16_t arfcn,
+                     uint8_t flags, uint16_t timeout, uint8_t sync_info_idx)
 {
        struct msgb *msg;
-       struct l1ctl_sync_new_ccch_req *req;
+       struct l1ctl_fbsb_req *req;
 
-       msg = osmo_l1_alloc(L1CTL_NEW_CCCH_REQ);
+       msg = osmo_l1_alloc(L1CTL_FBSB_REQ);
        if (!msg)
                return -1;
 
-       req = (struct l1ctl_sync_new_ccch_req *) msgb_put(msg, sizeof(*req));
-       req->band_arfcn = osmo_make_band_arfcn(ms);
+       req = (struct l1ctl_fbsb_req *) msgb_put(msg, sizeof(*req));
+       req->band_arfcn = htons(osmo_make_band_arfcn(ms, arfcn));
+       req->timeout = htons(timeout);
+       /* Threshold when to consider FB_MODE1: 4kHz - 1kHz */
+       req->freq_err_thresh1 = htons(4000 - 1000);
+       /* Threshold when to consider SCH: 1kHz - 200Hz */
+       req->freq_err_thresh2 = htons(1000 - 200);
+       /* not used yet! */
+       req->num_freqerr_avg = 3;
+       req->flags = flags;
+       req->sync_info_idx = sync_info_idx;
 
        return osmo_send_l1(ms, msg);
 }
@@ -267,7 +295,7 @@ int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr
        ul->link_id = 0;
        ul->tx_power = 0; /* FIXME: initial TX power */
        req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
-       req->band_arfcn = band_arfcn;
+       req->band_arfcn = htons(band_arfcn);
 
        return osmo_send_l1(ms, msg);
 }
@@ -314,6 +342,8 @@ static int rx_l1_reset(struct osmocom_ms *ms)
 {
        printf("Layer1 Reset.\n");
        dispatch_signal(SS_L1CTL, S_L1CTL_RESET, ms);
+
+       return 0;
 }
 
 /* Receive L1CTL_PM_RESP */
@@ -344,6 +374,7 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
        if (msgb_l2len(msg) < sizeof(*dl)) {
                LOGP(DL1C, LOGL_ERROR, "Short Layer2 message: %u\n",
                        msgb_l2len(msg));
+               msgb_free(msg);
                return -1;
        }
 
@@ -354,22 +385,26 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
        msg->l1h = l1h->data;
 
        switch (l1h->msg_type) {
-       case L1CTL_NEW_CCCH_RESP:
-               rc = rx_l1_ccch_resp(ms, msg);
+       case L1CTL_FBSB_RESP:
+               rc = rx_l1_fbsb_resp(ms, msg);
+               msgb_free(msg);
                break;
        case L1CTL_DATA_IND:
                rc = rx_ph_data_ind(ms, msg);
                break;
        case L1CTL_RESET:
                rc = rx_l1_reset(ms);
+               msgb_free(msg);
                break;
        case L1CTL_PM_RESP:
                rc = rx_l1_pm_resp(ms, msg);
+               msgb_free(msg);
                if (l1h->flags & L1CTL_F_DONE)
                        dispatch_signal(SS_L1CTL, S_L1CTL_PM_DONE, ms);
                break;
        default:
                fprintf(stderr, "Unknown MSG: %u\n", l1h->msg_type);
+               msgb_free(msg);
                break;
        }