dl = (struct l1ctl_info_dl *) msg->l1h;
- printf("RACH CONF: arfcn=%u fn=%u\n", dl->snr, ntohl(dl->frame_nr));
-
rc.fn = htonl(dl->frame_nr);
rc.ms = ms;
dispatch_signal(SS_L1CTL, S_L1CTL_RACH_CONF, &rc);
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)
}
/* 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;
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 = 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 = 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 = tx_power;
+
+ req = (struct l1ctl_dm_est_req *) msgb_put(msg, sizeof(*req));
+ 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);
}
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)
{
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)
{
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;
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");
- msgb_free(msg);
- 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: