/******************************************************************** Copyright ?2007 LGC Wireless, Inc. All rights reserved File Name: aifg_if.c Description: Interface of AIFG Version: v9.0.0 Author: Roy Jiang Create Date: 2007-3-12 History: 2007-3-6 v9.0.1 Create *********************************************************************/ #include "./include/aifg_var_ext.h" #include "../../public/src/include/license_id.h" /* Name: aifg_bind Purpose: Request to create a SAP in AIFG module. Input: aifg_sap_type type: type of upper layer entity int (*callback)(): pointer to call back function Output: SAP id */ int aifg_bind(aifg_sap_type type, int (*callback)(aifg_indication, aifg_msg_pre_decoded *)) { //checking parameters assert(type == AIFG_SAP_MSC || type == AIFG_SAP_BSC); assert(callback != NULL); assert(sap[type].enable == 0); if (wxc2_get_license(LIC_AIF) != 1) return -1; sap[type].enable = 1; sap[type].callback_func = callback; return (int)type; } /* Name: aifg_modify Purpose: Request to modify the SAP parameter in AIFG module. Input: aifg_sap_type type: type of upper layer entity aifg_callback_func *callback: new callback functions, null if no need to modify Output: None */ void aifg_modify(int sapid, int (*callback)(aifg_indication, aifg_msg_pre_decoded*)) { //checking parameters assert(sapid == AIFG_SAP_MSC || sapid == AIFG_SAP_BSC); assert(sap[sapid].enable == 1); sap[sapid].enable = 1; if(callback != NULL) sap[sapid].callback_func = callback; return; } /* Name: aifg_set_running_mode Purpose: Set the running mode of AIFG module. Input: enum aifg_run_mode mode: running mode, 0 - single, 1 - dual int alter_ip:IP address of the alternative server, hex format Output: None */ void aifg_set_running_mode(aifg_run_mode mode) { assert(mode == AIFG_RUN_MODE_SINGLE || mode == AIFG_RUN_MODE_DUAL); dual_server.mode = mode; return; } /* Name: aifg_createCircuitGroup Purpose: Request to create a circuit group in AIFG module. Input: int sapid: SAP ID of upper layer entity int dpc: DPC of the circuit group. aifg_ni ni: NI of the circuit group. Output: Circuit Group ID - Upper layer entity should record this ID and pass it to AIFG module whenever it request to send a message through this circuit group AIFG_ERR_NO_RESOURCE: Create failed */ int aifg_createCircuitGroup(int sapid, int dpc, aifg_ni ni, int tgid) { int i; assert(sapid == AIFG_SAP_MSC || sapid == AIFG_SAP_BSC); assert(ni >= 0 && ni <= 3); assert(dpc >= 0); if (sap[sapid].enable == 0) goto ERR_PROC; //check if there is a existing CG with the same dpc and ni for(i=0; i < AIFG_MAX_CG; i++){ if(cg[i].enable == 1 && cg[i].dpc == dpc && cg[i].ni == ni) return i; } //create a new circuit group i = 0; while(cg[i].enable == 1) i++; if(i >= AIFG_MAX_CG){ aifg_event = AIFG_ERR_OUT_OF_RESOURCE; goto ERR_PROC; } cg[i].enable = 1; cg[i].dpc = dpc; cg[i].ni = ni; cg[i].sapid = sapid; cg[i].tgid = tgid; return i; ERR_PROC: return -1; } /* Name: aifg_delCircuitGroup Purpose: Request to delete a circuit group in AIFG module. Input: int sapid: SAP ID of upper layer entity int cgid: Circuit Group ID Output: None */ void aifg_delCircuitGroup(int sapid, int cgid) { assert(sapid == AIFG_SAP_MSC || sapid == AIFG_SAP_BSC); assert(cgid >= 0 && cgid < AIFG_MAX_CG); cg[cgid].enable = 0; cg[cgid].dpc = 0; cg[cgid].ni = 0; cg[cgid].sapid = 0; cg[cgid].tgid = 0; return; } /* Name: aifg_modCircuitGroup Purpose: Request to modify the parameter of a circuit group in AIFG module. Input: int sapid: SAP ID of upper layer entity int cgid: Circuit Group ID int dpc: new DPC of the circuit group, -1 if no need to change. enum aifg_ni: new NI of the circuit group, -1 if no need to change. Output: Circuit Group ID - Upper layer entity should record this ID and pass it to AIFG module whenever it request to send a message through this circuit group */ int aifg_modCircuitGroup(int sapid, int cgid, int dpc, int ni) { assert(sapid == AIFG_SAP_MSC || sapid == AIFG_SAP_BSC); assert(cg[cgid].sapid == sapid); assert(ni >= 0 && ni <= 3); assert(dpc >= 0); assert(cgid >= 0 && cgid < AIFG_MAX_CG); cg[cgid].enable = 1; cg[cgid].dpc = dpc; cg[cgid].ni = ni; return cgid; } /* Name: aifg_send Purpose: Request to send a message through A-interface. Input: int sapid: SAP ID of upper layer entity. int cgid: Circuit Group ID int u_port: process port of upper layer entity aifg_msg *msg: content of assign request message Output: 0 - succeed -1 - failed, no free port available -2 - failed, circuit group not ready */ int aifg_send(int sapid, int cgid, int u_port, aifg_msg_t *msg) { int protocol; assert(sapid == AIFG_SAP_MSC || sapid == AIFG_SAP_BSC); assert(cgid >= 0 && cgid < AIFG_MAX_CG); assert(msg != NULL); if (sap[sapid].enable == 0){ aifg_event = AIFG_ERR_SAP_NOT_CREATED; goto ERR_PROC; } //check message protocol and pd msg->app_port = u_port; if(msg->id <= AIFG_MSG_ID_RP_SMMA){ if(msg->id <= AIFG_MSG_ID_MM_INFO) msg->pd = AIFG_PD_DTAP_MM; else if(msg->id <= AIFG_MSG_ID_FACILITY) msg->pd = AIFG_PD_DTAP_CC; else if(msg->id <= AIFG_MSG_ID_RELEASE_CMP_SS) msg->pd = AIFG_PD_DTAP_SS; else if(msg->id <= AIFG_MSG_ID_RP_SMMA) msg->pd = AIFG_PD_DTAP_SMS; else assert(0); protocol = AIFG_MSG_DTAP; } else{ if(msg->id <= AIFG_MSG_ID_HO_CAN_RESP) msg->pd = AIFG_PD_BSSMAP_GLOBAL; else if(msg->id <= AIFG_MSG_ID_LSA_INFO) msg->pd = AIFG_PD_BSSMAP_DEDICATED; else assert(0); protocol = AIFG_MSG_BSSMAP; } if(msg->aif_port == -1 || msg->pd == AIFG_PD_BSSMAP_GLOBAL){ if(msg->pd != AIFG_PD_BSSMAP_GLOBAL || msg->id == AIFG_MSG_ID_PAGING){ if((msg->aif_port = aifg_port_assign(sapid, cgid, -1)) < 0){ aifg_event = AIFG_ERR_ASSIGN_PORT_FAIL; goto ERR_PROC; } aifg_pcb[msg->aif_port].upper_port = u_port; aifg_pcb[msg->aif_port].trace_flag = msg->trace_flag; } else{ msg->aif_port = -1; //no port need aifg_send_udt(cgid, msg, NULL); //global BSSMAP message needs no aifg port, except paging } } else if (aifg_pcb[msg->aif_port].stat == AIFG_PORT_TRANSACTION && aifg_pcb[msg->aif_port].ti_type != AIFG_TRANS_UNKNOW){ if((msg->id == AIFG_MSG_ID_SETUP && (aifg_pcb[msg->aif_port].ti_stat > 0 || aifg_pcb[msg->aif_port].ti_type != AIFG_TRANS_CC)) || (msg->id == AIFG_MSG_ID_RP_DATA && aifg_pcb[msg->aif_port].ti_type != AIFG_TRANS_SMS)) { //new transaction int new_port = aifg_port_assign(sapid, cgid, -1); if (new_port < 0){ aifg_event = AIFG_ERR_ASSIGN_PORT_FAIL; goto ERR_PROC; } aifg_pcb[new_port].upper_port = u_port; aifg_pcb[new_port].link_id = aifg_pcb[msg->aif_port].link_id; aifg_pcb[new_port].trace_flag = msg->trace_flag; msg->aif_port = new_port; } } if(msg->aif_port != -1){ if (aifg_pcb[msg->aif_port].stat == AIFG_PORT_IDLE){ aifg_event = AIFG_ERR_MSG_SD_TO_IDLE_PORT; goto ERR_PROC; } aifg_pcb[msg->aif_port].cgid = cgid; aifg_port_proc(&aifg_pcb[msg->aif_port], msg, NULL); } aifg_debug_print(msg->aif_port, AIFG_EVENT_RV_REQ, msg, 0); return AIFG_SUCCEED; ERR_PROC: aifg_debug_print(msg->aif_port, aifg_event, msg, u_port); return AIFG_ERROR; }