uint32 MEMORY::read_data32(uint32 addr) { int bank = (addr & ADDR_MASK) >> addr_shift; if(read_table[bank].dev != NULL) { return read_table[bank].dev->read_memory_mapped_io32(addr); } else { uint32 val = read_data16(addr); val |= read_data16(addr + 2) << 16; return val; } }
/* * Handle the assignment request message. * * See §3.2.1.1 for the message type */ static int bssmap_handle_assignm_req(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int length) { struct msgb *resp; struct osmo_msc_data *msc; struct tlv_parsed tp; uint8_t *data; uint8_t timeslot; uint8_t multiplex; enum gsm48_chan_mode chan_mode = GSM48_CMODE_SIGN; int i, supported, port, full_rate = -1; if (!conn->conn) { LOGP(DMSC, LOGL_ERROR, "No lchan/msc_data in cipher mode command.\n"); return -1; } tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, length - 1, 0, 0); if (!TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_TYPE)) { LOGP(DMSC, LOGL_ERROR, "Mandatory channel type not present.\n"); goto reject; } if (!TLVP_PRESENT(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE)) { LOGP(DMSC, LOGL_ERROR, "Identity code missing. Audio routing will not work.\n"); goto reject; } conn->cic = ntohs(read_data16(TLVP_VAL(&tp, GSM0808_IE_CIRCUIT_IDENTITY_CODE))); timeslot = conn->cic & 0x1f; multiplex = (conn->cic & ~0x1f) >> 5; /* * Currently we only support a limited subset of all * possible channel types. The limitation ends by not using * multi-slot, limiting the channel coding, speech... */ if (TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE) < 3) { LOGP(DMSC, LOGL_ERROR, "ChannelType len !=3 not supported: %d\n", TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE)); goto reject; } /* * Try to figure out if we support the proposed speech codecs. For * now we will always pick the full rate codecs. */ data = (uint8_t *) TLVP_VAL(&tp, GSM0808_IE_CHANNEL_TYPE); if ((data[0] & 0xf) != 0x1) { LOGP(DMSC, LOGL_ERROR, "ChannelType != speech: %d\n", data[0]); goto reject; } /* * go through the list of preferred codecs of our gsm network * and try to find it among the permitted codecs. If we found * it we will send chan_mode to the right mode and break the * inner loop. The outer loop will exit due chan_mode having * the correct value. */ full_rate = 0; msc = conn->msc; for (supported = 0; chan_mode == GSM48_CMODE_SIGN && supported < msc->audio_length; ++supported) { int perm_val = audio_support_to_gsm88(msc->audio_support[supported]); for (i = 2; i < TLVP_LEN(&tp, GSM0808_IE_CHANNEL_TYPE); ++i) { if ((data[i] & 0x7f) == perm_val) { chan_mode = gsm88_to_chan_mode(perm_val); full_rate = (data[i] & 0x4) == 0; break; } else if ((data[i] & 0x80) == 0x00) { break; } } } if (chan_mode == GSM48_CMODE_SIGN) { LOGP(DMSC, LOGL_ERROR, "No supported audio type found.\n"); goto reject; } /* map it to a MGCP Endpoint and a RTP port */ port = mgcp_timeslot_to_endpoint(multiplex, timeslot); conn->rtp_port = rtp_calculate_port(port, msc->rtp_base); return gsm0808_assign_req(conn->conn, chan_mode, full_rate); reject: resp = gsm0808_create_assignment_failure(GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE, NULL); if (!resp) { LOGP(DMSC, LOGL_ERROR, "Channel allocation failure.\n"); return -1; } bsc_queue_for_msc(conn, resp); return -1; }
/* GSM 08.08 § 3.2.1.19 */ static int bssmap_handle_paging(struct osmo_msc_data *msc, struct msgb *msg, unsigned int payload_length) { struct gsm_subscriber *subscr; struct tlv_parsed tp; char mi_string[GSM48_MI_SIZE]; uint32_t tmsi = GSM_RESERVED_TMSI; unsigned int lac = GSM_LAC_RESERVED_ALL_BTS; uint8_t data_length; const uint8_t *data; uint8_t chan_needed = RSL_CHANNEED_ANY; tlv_parse(&tp, gsm0808_att_tlvdef(), msg->l4h + 1, payload_length - 1, 0, 0); if (!TLVP_PRESENT(&tp, GSM0808_IE_IMSI)) { LOGP(DMSC, LOGL_ERROR, "Mandatory IMSI not present.\n"); return -1; } else if ((TLVP_VAL(&tp, GSM0808_IE_IMSI)[0] & GSM_MI_TYPE_MASK) != GSM_MI_TYPE_IMSI) { LOGP(DMSC, LOGL_ERROR, "Wrong content in the IMSI\n"); return -1; } if (!TLVP_PRESENT(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST)) { LOGP(DMSC, LOGL_ERROR, "Mandatory CELL IDENTIFIER LIST not present.\n"); return -1; } if (TLVP_PRESENT(&tp, GSM0808_IE_TMSI) && TLVP_LEN(&tp, GSM0808_IE_TMSI) == 4) { tmsi = ntohl(tlvp_val32_unal(&tp, GSM0808_IE_TMSI)); } /* * parse the IMSI */ gsm48_mi_to_string(mi_string, sizeof(mi_string), TLVP_VAL(&tp, GSM0808_IE_IMSI), TLVP_LEN(&tp, GSM0808_IE_IMSI)); /* * parse the cell identifier list */ data_length = TLVP_LEN(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST); data = TLVP_VAL(&tp, GSM0808_IE_CELL_IDENTIFIER_LIST); /* * Support paging to all network or one BTS at one LAC */ if (data_length == 3 && data[0] == CELL_IDENT_LAC) { lac = ntohs(read_data16(&data[1])); } else if (data_length > 1 || (data[0] & 0x0f) != CELL_IDENT_BSS) { LOGP(DMSC, LOGL_ERROR, "Unsupported Cell Identifier List: %s\n", osmo_hexdump(data, data_length)); return -1; } if (TLVP_PRESENT(&tp, GSM0808_IE_CHANNEL_NEEDED) && TLVP_LEN(&tp, GSM0808_IE_CHANNEL_NEEDED) == 1) chan_needed = TLVP_VAL(&tp, GSM0808_IE_CHANNEL_NEEDED)[0] & 0x03; if (TLVP_PRESENT(&tp, GSM0808_IE_EMLPP_PRIORITY)) { LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n"); } subscr = subscr_get_or_create(msc->network->subscr_group, mi_string); if (!subscr) { LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string); return -1; } subscr->lac = lac; subscr->tmsi = tmsi; LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac); bsc_grace_paging_request(subscr, chan_needed, msc); return 0; }