[layer23] Updated layer23 to current L1 support and forthcomming hopping.
[osmocom-bb.git] / src / host / layer23 / src / l1ctl.c
index 1239b99..8d5e569 100644 (file)
@@ -103,6 +103,26 @@ static int rx_l1_fbsb_conf(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+static int rx_l1_rach_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+       struct l1ctl_info_dl *dl;
+       struct osmobb_rach_conf rc;
+
+       if (msgb_l3len(msg) < sizeof(*dl)) {
+               LOGP(DL1C, LOGL_ERROR, "RACH CONF: MSG too short %u\n",
+                       msgb_l3len(msg));
+               return -1;
+       }
+
+       dl = (struct l1ctl_info_dl *) msg->l1h;
+
+       rc.fn = htonl(dl->frame_nr);
+       rc.ms = ms;
+       dispatch_signal(SS_L1CTL, S_L1CTL_RACH_CONF, &rc);
+
+       return 0;
+}
+
 char *chan_nr2string(uint8_t chan_nr)
 {
        static char str[20];
@@ -188,6 +208,26 @@ static int rx_ph_data_ind(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+/* Receive L1CTL_DATA_CONF (Data Confirm from L1) */
+static int rx_ph_data_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+       struct l1ctl_info_dl *dl;
+       struct lapdm_entity *le;
+
+       dl = (struct l1ctl_info_dl *) msg->l1h;
+
+       /* determine LAPDm entity based on SACCH or not */
+       if (dl->link_id & 0x40)
+               le = &ms->l2_entity.lapdm_acch;
+       else
+               le = &ms->l2_entity.lapdm_dcch;
+
+       /* send it up into LAPDm */
+       l2_ph_data_conf(msg, le);
+
+       return 0;
+}
+
 /* Transmit L1CTL_DATA_REQ */
 int tx_ph_data_req(struct osmocom_ms *ms, struct msgb *msg,
                   uint8_t chan_nr, uint8_t link_id)
@@ -296,7 +336,8 @@ int tx_ph_rach_req(struct osmocom_ms *ms)
 }
 
 /* Transmit L1CTL_DM_EST_REQ */
-int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr)
+int tx_ph_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn,
+       uint8_t chan_nr, uint8_t tsc, uint8_t tx_power)
 {
        struct msgb *msg;
        struct l1ctl_info_ul *ul;
@@ -308,12 +349,66 @@ int tx_ph_dm_est_req(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr
 
        DEBUGP(DL1C, "Tx Dedic.Mode Est Req (arfcn=%u, chan_nr=0x%02x)\n",
                band_arfcn, chan_nr);
+
+       ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
+       ul->chan_nr = chan_nr;
+       ul->link_id = 0;
+       ul->tx_power = tx_power;
+
+       req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
+       req->tsc = tsc;
+       req->h = 0;
+       req->h0.band_arfcn = htons(band_arfcn);
+
+       return osmo_send_l1(ms, msg);
+}
+
+int tx_ph_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn,
+       uint16_t *ma, uint8_t ma_len, uint8_t chan_nr, uint8_t tsc,
+       uint8_t tx_power)
+{
+       struct msgb *msg;
+       struct l1ctl_info_ul *ul;
+       struct l1ctl_dm_est_req *req;
+       int i;
+
+       msg = osmo_l1_alloc(L1CTL_DM_EST_REQ);
+       if (!msg)
+               return -1;
+
+       DEBUGP(DL1C, "Tx Dedic.Mode Est Req (maio=%u, hsn=%u, "
+               "chan_nr=0x%02x)\n", maio, hsn, chan_nr);
+
        ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
        ul->chan_nr = chan_nr;
        ul->link_id = 0;
-       ul->tx_power = 0; /* FIXME: initial TX power */
+       ul->tx_power = tx_power;
+
        req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
-       req->band_arfcn = htons(band_arfcn);
+       req->tsc = tsc;
+       req->h = 1;
+       req->h1.maio = maio;
+       req->h1.hsn = hsn;
+       req->h1.n = ma_len;
+       for (i = 0; i < ma_len; i++)
+               req->h1.ma[i] = htons(ma[i]);
+
+       return osmo_send_l1(ms, msg);
+}
+
+/* Transmit L1CTL_DM_REL_REQ */
+int tx_ph_dm_rel_req(struct osmocom_ms *ms)
+{
+       struct msgb *msg;
+       struct l1ctl_info_ul *ul;
+
+       msg = osmo_l1_alloc(L1CTL_DM_REL_REQ);
+       if (!msg)
+               return -1;
+
+       DEBUGP(DL1C, "Tx Dedic.Mode Rel Req\n");
+
+       ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul));
 
        return osmo_send_l1(ms, msg);
 }
@@ -355,6 +450,23 @@ int l1ctl_tx_pm_req_range(struct osmocom_ms *ms, uint16_t arfcn_from,
        return osmo_send_l1(ms, msg);
 }
 
+/* Transmit L1CTL_RESET_REQ */
+int l1ctl_tx_reset_req(struct osmocom_ms *ms, uint8_t type)
+{
+       struct msgb *msg;
+       struct l1ctl_reset *res;
+
+       msg = osmo_l1_alloc(L1CTL_RESET_REQ);
+       if (!msg)
+               return -1;
+
+       printf("Tx Reset Req (%u)\n", type);
+       res = (struct l1ctl_reset *) msgb_put(msg, sizeof(*res));
+       res->type = type;
+
+       return osmo_send_l1(ms, msg);
+}
+
 /* Receive L1CTL_RESET_IND */
 static int rx_l1_reset(struct osmocom_ms *ms)
 {
@@ -382,6 +494,29 @@ static int rx_l1_pm_conf(struct osmocom_ms *ms, struct msgb *msg)
        return 0;
 }
 
+/* Receive L1CTL_MODE_CONF */
+static int rx_l1_ccch_mode_conf(struct osmocom_ms *ms, struct msgb *msg)
+{
+       struct osmobb_ccch_mode_conf mc;
+       struct l1ctl_ccch_mode_conf *conf;
+
+       if (msgb_l3len(msg) < sizeof(*conf)) {
+               LOGP(DL1C, LOGL_ERROR, "MODE CONF: MSG too short %u\n",
+                       msgb_l3len(msg));
+               return -1;
+       }
+
+       conf = (struct l1ctl_ccch_mode_conf *) msg->l1h;
+
+       printf("mode=%u\n", conf->ccch_mode);
+
+       mc.ccch_mode = conf->ccch_mode;
+       mc.ms = ms;
+       dispatch_signal(SS_L1CTL, S_L1CTL_CCCH_MODE_CONF, &mc);
+
+       return 0;
+}
+
 /* Receive incoming data from L1 using L1CTL format */
 int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
 {
@@ -410,7 +545,11 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
        case L1CTL_DATA_IND:
                rc = rx_ph_data_ind(ms, msg);
                break;
+       case L1CTL_DATA_CONF:
+               rc = rx_ph_data_conf(ms, msg);
+               break;
        case L1CTL_RESET_IND:
+       case L1CTL_RESET_CONF:
                rc = rx_l1_reset(ms);
                msgb_free(msg);
                break;
@@ -420,14 +559,13 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg)
                if (l1h->flags & L1CTL_F_DONE)
                        dispatch_signal(SS_L1CTL, S_L1CTL_PM_DONE, ms);
                break;
-       case L1CTL_RESET_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_RESET_CONF\n");
-               break;
        case L1CTL_RACH_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_RACH_CONF\n");
+               rc = rx_l1_rach_conf(ms, msg);
+               msgb_free(msg);
                break;
-       case L1CTL_DATA_CONF:
-               LOGP(DL1C, LOGL_NOTICE, "L1CTL_DATA_CONF\n");
+       case L1CTL_CCCH_MODE_CONF:
+               rc = rx_l1_ccch_mode_conf(ms, msg);
+               msgb_free(msg);
                break;
        default:
                fprintf(stderr, "Unknown MSG: %u\n", l1h->msg_type);