diff options
author | Andreas.Eversberg <jolly@eversberg.eu> | 2011-07-28 20:54:42 +0200 |
---|---|---|
committer | Sylvain Munaut <tnt@246tNt.com> | 2011-07-28 21:30:51 +0200 |
commit | 1a5461fb2beb96bfa004245a102cd4c1422baa2a (patch) | |
tree | 71b3dce4ea3765b61610015b58c79c2322127456 /src/host/layer23/src/common/l1ctl.c | |
parent | e042cbb29763f21fd2ed7076c15db87b037ce73a (diff) |
layer23: Add mobile support for sending / receiving voice frame through MNCC
Support GSM FR codec only so far.
Written-by: Andreas Eversberg <jolly@eversberg.eu>
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'src/host/layer23/src/common/l1ctl.c')
-rw-r--r-- | src/host/layer23/src/common/l1ctl.c | 130 |
1 files changed, 124 insertions, 6 deletions
diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c index a249ed71..e3ab4c9c 100644 --- a/src/host/layer23/src/common/l1ctl.c +++ b/src/host/layer23/src/common/l1ctl.c @@ -46,6 +46,7 @@ #include <osmocom/bb/common/l1l2_interface.h> #include <osmocom/bb/common/lapdm.h> #include <osmocom/bb/common/logging.h> +#include <osmocom/codec/codec.h> extern struct gsmtap_inst *gsmtap_inst; @@ -67,6 +68,23 @@ static struct msgb *osmo_l1_alloc(uint8_t msg_type) } +static inline int msb_get_bit(uint8_t *buf, int bn) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + return (buf[pos_byte] >> pos_bit) & 1; +} + +static inline void msb_set_bit(uint8_t *buf, int bn, int bit) +{ + int pos_byte = bn >> 3; + int pos_bit = 7 - (bn & 7); + + buf[pos_byte] |= (bit << pos_bit); +} + + static int osmo_make_band_arfcn(struct osmocom_ms *ms, uint16_t arfcn) { /* TODO: Include the band */ @@ -356,7 +374,8 @@ int l1ctl_tx_ccch_mode_req(struct osmocom_ms *ms, uint8_t ccch_mode) } /* Transmit L1CTL_TCH_MODE_REQ */ -int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode) +int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode, + uint8_t audio_mode) { struct msgb *msg; struct l1ctl_tch_mode_req *req; @@ -369,7 +388,7 @@ int l1ctl_tx_tch_mode_req(struct osmocom_ms *ms, uint8_t tch_mode) req = (struct l1ctl_tch_mode_req *) msgb_put(msg, sizeof(*req)); req->tch_mode = tch_mode; - req->audio_mode = AUDIO_TX_MICROPHONE | AUDIO_RX_SPEAKER; + req->audio_mode = audio_mode; return osmo_send_l1(ms, msg); } @@ -440,7 +459,8 @@ int l1ctl_tx_rach_req(struct osmocom_ms *ms, uint8_t ra, uint16_t offset, /* Transmit L1CTL_DM_EST_REQ */ int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn, - uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode) + uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode, + uint8_t audio_mode) { struct msgb *msg; struct l1ctl_info_ul *ul; @@ -462,14 +482,15 @@ int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn, req->h = 0; req->h0.band_arfcn = htons(band_arfcn); req->tch_mode = tch_mode; - req->audio_mode = AUDIO_TX_MICROPHONE | AUDIO_RX_SPEAKER; + req->audio_mode = audio_mode; return osmo_send_l1(ms, msg); } int l1ctl_tx_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 tch_mode) + uint8_t chan_nr, uint8_t tsc, uint8_t tch_mode, + uint8_t audio_mode) { struct msgb *msg; struct l1ctl_info_ul *ul; @@ -496,7 +517,7 @@ int l1ctl_tx_dm_est_req_h1(struct osmocom_ms *ms, uint8_t maio, uint8_t hsn, for (i = 0; i < ma_len; i++) req->h1.ma[i] = htons(ma[i]); req->tch_mode = tch_mode; - req->audio_mode = AUDIO_TX_MICROPHONE | AUDIO_RX_SPEAKER; + req->audio_mode = audio_mode; return osmo_send_l1(ms, msg); } @@ -732,12 +753,103 @@ static int rx_l1_tch_mode_conf(struct osmocom_ms *ms, struct msgb *msg) LOGP(DL1C, LOGL_INFO, "TCH MODE CONF: mode=%u\n", conf->tch_mode); mc.tch_mode = conf->tch_mode; + mc.audio_mode = conf->audio_mode; mc.ms = ms; osmo_signal_dispatch(SS_L1CTL, S_L1CTL_TCH_MODE_CONF, &mc); return 0; } +/* Receive L1CTL_TRAFFIC_IND (Traffic Indication from L1) */ +static int rx_l1_traffic_ind(struct osmocom_ms *ms, struct msgb *msg) +{ + struct l1ctl_info_dl *dl; + struct l1ctl_traffic_ind *ti; + uint8_t fr[33]; + int i, di, si; + + /* Header handling */ + dl = (struct l1ctl_info_dl *) msg->l1h; + msg->l2h = dl->payload; + ti = (struct l1ctl_traffic_ind *) msg->l2h; + + memset(fr, 0x00, 33); + fr[0] = 0xd0; + for (i = 0; i < 260; i++) { + di = gsm610_bitorder[i]; + si = (i > 181) ? i + 4 : i; + msb_set_bit(fr, 4 + di, msb_get_bit(ti->data, si)); + } + memcpy(ti->data, fr, 33); + + DEBUGP(DL1C, "TRAFFIC IND (%s)\n", osmo_hexdump(ti->data, 33)); + + /* distribute or drop */ + if (ms->l1_entity.l1_traffic_ind) { + /* pull the L1 header from the msgb */ + msgb_pull(msg, msg->l2h - (msg->l1h-sizeof(struct l1ctl_hdr))); + msg->l1h = NULL; + + return ms->l1_entity.l1_traffic_ind(ms, msg); + } + + msgb_free(msg); + return 0; +} + +/* Transmit L1CTL_TRAFFIC_REQ (Traffic Request to L1) */ +int l1ctl_tx_traffic_req(struct osmocom_ms *ms, struct msgb *msg, + uint8_t chan_nr, uint8_t link_id) +{ + struct l1ctl_hdr *l1h; + struct l1ctl_info_ul *l1i_ul; + struct l1ctl_traffic_req *tr; + uint8_t fr[33]; + int i, di, si; + + /* Header handling */ + tr = (struct l1ctl_traffic_req *) msg->l2h; + + DEBUGP(DL1C, "TRAFFIC REQ (%s)\n", + osmo_hexdump(msg->l2h, msgb_l2len(msg))); + + if (msgb_l2len(msg) != 33) { + LOGP(DL1C, LOGL_ERROR, "Traffic Request has incorrect length " + "(%u != 33)\n", msgb_l2len(msg)); + msgb_free(msg); + return -EINVAL; + } + + if ((tr->data[0] >> 4) != 0xd) { + LOGP(DL1C, LOGL_ERROR, "Traffic Request has incorrect magic " + "(%u != 0xd)\n", tr->data[0] >> 4); + msgb_free(msg); + return -EINVAL; + } + + memset(fr, 0x00, 33); + for (i = 0; i < 260; i++) { + si = gsm610_bitorder[i]; + di = (i > 181) ? i + 4 : i; + msb_set_bit(fr, di, msb_get_bit(tr->data, 4 + si)); + } + memcpy(tr->data, fr, 33); +// printf("TX %s\n", osmo_hexdump(tr->data, 33)); + + /* prepend uplink info header */ + l1i_ul = (struct l1ctl_info_ul *) msgb_push(msg, sizeof(*l1i_ul)); + + l1i_ul->chan_nr = chan_nr; + l1i_ul->link_id = link_id; + + /* prepend l1 header */ + msg->l1h = msgb_push(msg, sizeof(*l1h)); + l1h = (struct l1ctl_hdr *) msg->l1h; + l1h->msg_type = L1CTL_TRAFFIC_REQ; + + return osmo_send_l1(ms, msg); +} + /* Transmit L1CTL_NEIGH_PM_REQ */ int l1ctl_tx_neigh_pm_req(struct osmocom_ms *ms, int num, uint16_t *arfcn) { @@ -837,6 +949,12 @@ int l1ctl_recv(struct osmocom_ms *ms, struct msgb *msg) rc = rx_l1_neigh_pm_ind(ms, msg); msgb_free(msg); break; + case L1CTL_TRAFFIC_IND: + rc = rx_l1_traffic_ind(ms, msg); + break; + case L1CTL_TRAFFIC_CONF: + msgb_free(msg); + break; default: LOGP(DL1C, LOGL_ERROR, "Unknown MSG: %u\n", l1h->msg_type); msgb_free(msg); |