diff --git a/include/openbsc/gsm_data.h b/include/openbsc/gsm_data.h index 99634f4c1..75009584e 100644 --- a/include/openbsc/gsm_data.h +++ b/include/openbsc/gsm_data.h @@ -150,6 +150,8 @@ struct gsm_network { void (*update_request_accepted)(struct gsm_bts *, u_int32_t); void (*channel_allocated)(struct gsm_lchan *bts, enum gsm_chreq_reason_t); + void (*channel_acked)(struct gsm_lchan *); + void (*channel_nacked)(struct gsm_lchan *); }; struct gsm_network *gsm_network_init(unsigned int num_bts, u_int16_t country_code, diff --git a/src/abis_rsl.c b/src/abis_rsl.c index 03498e9fe..cf792538a 100644 --- a/src/abis_rsl.c +++ b/src/abis_rsl.c @@ -455,6 +455,8 @@ int rsl_data_request(struct msgb *msg, u_int8_t link_id) /* Chapter 8.4.2: Channel Activate Acknowledge */ static int rsl_rx_chan_act_ack(struct msgb *msg) { + struct gsm_lchan *lchan; + struct gsm_network *network; struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg); /* BTS has confirmed channel activation, we now need @@ -464,12 +466,20 @@ static int rsl_rx_chan_act_ack(struct msgb *msg) DEBUGP(DRSL, "Channel Activate ACK Channel 0x%02x\n", rslh->chan_nr); + lchan = lchan_lookup(msg->trx, rslh->chan_nr); + network = msg->trx->bts->network; + if (network->channel_acked) + (*network->channel_acked)(lchan); + + return 0; } /* Chapter 8.4.3: Channel Activate NACK */ static int rsl_rx_chan_act_nack(struct msgb *msg) { + struct gsm_lchan *lchan; + struct gsm_network *network; struct abis_rsl_dchan_hdr *rslh = msgb_l2(msg); /* BTS has confirmed channel activation, we now need @@ -479,6 +489,11 @@ static int rsl_rx_chan_act_nack(struct msgb *msg) DEBUGP(DRSL, "Channel Activate NACK Channel 0x%02x\n", rslh->chan_nr); + lchan = lchan_lookup(msg->trx, rslh->chan_nr); + network = msg->trx->bts->network; + if (network->channel_nacked) + (*network->channel_nacked)(lchan); + return 0; } diff --git a/src/bsc_hack.c b/src/bsc_hack.c index 1cf0731f4..a0b635d65 100644 --- a/src/bsc_hack.c +++ b/src/bsc_hack.c @@ -52,6 +52,8 @@ static const char *database_name = "hlr.sqlite3"; static void bsc_hack_update_request_accepted(struct gsm_bts *bts, u_int32_t assigned_tmi); static void bsc_hack_channel_allocated(struct gsm_lchan *chan, enum gsm_chreq_reason_t reason); +static void bsc_hack_channel_acked(struct gsm_lchan *chan); +static void bsc_hack_channel_nacked(struct gsm_lchan *chan); /* The following definitions are for OM and NM packets that we cannot yet @@ -643,6 +645,8 @@ static int bootstrap_network(void) bts->trx[0].arfcn = HARDCODED_ARFCN; gsmnet->update_request_accepted = bsc_hack_update_request_accepted; gsmnet->channel_allocated = bsc_hack_channel_allocated; + gsmnet->channel_acked = bsc_hack_channel_acked; + gsmnet->channel_nacked = bsc_hack_channel_nacked; if (mi_setup(bts, 0, mi_cb) < 0) return -EIO; @@ -836,6 +840,55 @@ static void bsc_hack_channel_allocated(struct gsm_lchan *chan, del_timer(&pag_timer); } +static void bsc_hack_channel_acked(struct gsm_lchan *lchan) +{ + struct pending_registered_station *station; + if (llist_empty(&pending_stations)) { + DEBUGP(DPAG, "Channel nacked but nothing pending\n"); + return; + } + + station = (struct pending_registered_station*) pending_stations.next; + if (station->tmsi != (u_int32_t)lchan->user_data) { + DEBUGP(DPAG, "Hmmm the channel is not allocated by the" + "station we wanted channel: %u us:%u\n", + (u_int32_t)(lchan->user_data), station->tmsi); + return; + } + + DEBUGP(DPAG, "We have probably paged a channel for tmsi: %u on %d\n", + station->tmsi, lchan->nr); + + llist_del(&station->entry); + free(station); +} + +/* failed... remove from the list */ +static void bsc_hack_channel_nacked(struct gsm_lchan *lchan) +{ + struct pending_registered_station *station; + if (llist_empty(&pending_stations)) { + DEBUGP(DPAG, "Channel nacked but nothing pending\n"); + return; + } + + station = (struct pending_registered_station*) pending_stations.next; + if (station->tmsi != (u_int32_t)lchan->user_data) { + DEBUGP(DPAG, "Hmmm the channel is not allocated by the" + "station we wanted channel: %u us:%u\n", + (u_int32_t)(lchan->user_data), station->tmsi); + return; + } + + + /* + * give up and go to the next channel + */ + llist_del(&station->entry); + free(station); + pag_timer_cb(0); +} + int main(int argc, char **argv) { /* parse options */