aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm_04_08.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2008-12-27 16:32:52 +0000
committerHarald Welte <laforge@gnumonks.org>2008-12-27 16:32:52 +0000
commit4bc90a160af88b72c15a093ef885e98da6b4cd24 (patch)
tree2ecf76f4e8d440e91b43f7a608df41bdc2e92b8b /src/gsm_04_08.c
parent7eda3ab3c846398d20832d55aec38637e5849a6b (diff)
add minimal MO call state transitions
Diffstat (limited to 'src/gsm_04_08.c')
-rw-r--r--src/gsm_04_08.c207
1 files changed, 133 insertions, 74 deletions
diff --git a/src/gsm_04_08.c b/src/gsm_04_08.c
index 239ece3c2..f135013fa 100644
--- a/src/gsm_04_08.c
+++ b/src/gsm_04_08.c
@@ -124,80 +124,6 @@ static int gsm0408_sendmsg(struct msgb *msg)
return rsl_data_request(msg, 0);
}
-static int gsm48_cc_tx_status(struct gsm_lchan *lchan)
-{
- struct msgb *msg = gsm48_msgb_alloc();
- struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
- u_int8_t *cause, *call_state;
-
- msg->lchan = lchan;
-
- gh->proto_discr = GSM48_PDISC_CC;
- gh->msg_type = GSM48_MT_CC_STATUS;
-
- cause = msgb_put(msg, 3);
- cause[0] = 2;
- cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
- cause[2] = 0x80 | 30; /* response to status inquiry */
-
- call_state = msgb_put(msg, 1);
- call_state[0] = 0xc0 | 0x00;
-
- return gsm0408_sendmsg(msg);
-}
-
-static int gsm48_cc_rx_status_enq(struct msgb *msg)
-{
- return gsm48_cc_tx_status(msg->lchan);
-}
-
-static int gsm0408_rcv_cc(struct msgb *msg)
-{
- struct gsm48_hdr *gh = msgb_l3(msg);
- u_int8_t msg_type = gh->msg_type & 0xbf;
- int rc = 0;
-
- switch (msg_type) {
- case GSM48_MT_CC_CALL_CONF:
- /* Response to SETUP */
- DEBUGP(DCC, "CALL CONFIRM\n");
- break;
- case GSM48_MT_CC_RELEASE_COMPL:
- DEBUGP(DCC, "RELEASE COMPLETE\n");
- break;
- case GSM48_MT_CC_ALERTING:
- DEBUGP(DCC, "ALERTING\n");
- break;
- case GSM48_MT_CC_CONNECT:
- DEBUGP(DCC, "CONNECT\n");
- /* need to respond with CONNECT_ACK */
- break;
- case GSM48_MT_CC_RELEASE:
- DEBUGP(DCC, "RELEASE\n");
- /* need to respond with RELEASE_COMPLETE */
- break;
- case GSM48_MT_CC_STATUS_ENQ:
- rc = gsm48_cc_rx_status_enq(msg);
- break;
- case GSM48_MT_CC_DISCONNECT:
- DEBUGP(DCC, "DISCONNECT\n");
- break;
- case GSM48_MT_CC_SETUP:
- DEBUGP(DCC, "SETUP\n");
- /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
- break;
- case GSM48_MT_CC_EMERG_SETUP:
- DEBUGP(DCC, "EMERGENCY SETUP\n");
- /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
- break;
- default:
- fprintf(stderr, "Unimplemented GSM 04.08 msg type 0x%02x\n",
- msg_type);
- break;
- }
-
- return rc;
-}
/* Chapter 9.2.14 : Send LOCATION UPDATE REJECT */
int gsm0408_loc_upd_rej(struct gsm_lchan *lchan, u_int8_t cause)
@@ -462,6 +388,139 @@ static int gsm0408_rcv_rr(struct msgb *msg)
return 0;
}
+/* Call Control */
+
+/* Send a 04.08 call control message, add transaction ID and TI flag */
+static int gsm48_cc_sendmsg(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msg->data;
+ struct gsm_call *call = &msg->lchan->call;
+
+ gh->proto_discr |= msg->lchan->call.transaction_id;
+
+ /* GSM 04.07 Section 11.2.3.1.3 */
+ switch (call->type) {
+ case GSM_CT_MO:
+ gh->proto_discr |= 0x80;
+ break;
+ case GSM_CT_MT:
+ break;
+ }
+
+ return gsm0408_sendmsg(msg);
+}
+
+
+static int gsm48_cc_tx_status(struct gsm_lchan *lchan)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ u_int8_t *cause, *call_state;
+
+ msg->lchan = lchan;
+
+ gh->proto_discr = GSM48_PDISC_CC;
+ gh->msg_type = GSM48_MT_CC_STATUS;
+
+ cause = msgb_put(msg, 3);
+ cause[0] = 2;
+ cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
+ cause[2] = 0x80 | 30; /* response to status inquiry */
+
+ call_state = msgb_put(msg, 1);
+ call_state[0] = 0xc0 | 0x00;
+
+ return gsm48_cc_sendmsg(msg);
+}
+
+static int gsm48_cc_tx_simple(struct gsm_lchan *lchan, u_int8_t msg_type)
+{
+ struct msgb *msg = gsm48_msgb_alloc();
+ struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+
+ msg->lchan = lchan;
+
+ gh->proto_discr = GSM48_PDISC_CC;
+ gh->msg_type = msg_type;
+
+ return gsm48_cc_sendmsg(msg);
+}
+
+static int gsm48_cc_rx_status_enq(struct msgb *msg)
+{
+ return gsm48_cc_tx_status(msg->lchan);
+}
+
+static int gsm48_cc_rx_setup(struct msgb *msg)
+{
+ return gsm48_cc_tx_simple(msg->lchan, GSM48_MT_CC_CALL_CONF);
+}
+
+static int gsm0408_rcv_cc(struct msgb *msg)
+{
+ struct gsm48_hdr *gh = msgb_l3(msg);
+ u_int8_t msg_type = gh->msg_type & 0xbf;
+ struct gsm_call *call = &msg->lchan->call;
+ int rc = 0;
+
+ switch (msg_type) {
+ case GSM48_MT_CC_CALL_CONF:
+ /* Response to SETUP */
+ DEBUGP(DCC, "CALL CONFIRM\n");
+ break;
+ case GSM48_MT_CC_RELEASE_COMPL:
+ /* Answer from MS to RELEASE */
+ DEBUGP(DCC, "RELEASE COMPLETE (state->NULL)\n");
+ call->state = GSM_CSTATE_NULL;
+ break;
+ case GSM48_MT_CC_ALERTING:
+ DEBUGP(DCC, "ALERTING\n");
+ break;
+ case GSM48_MT_CC_CONNECT:
+ DEBUGP(DCC, "CONNECT\n");
+ /* MT: need to respond with CONNECT_ACK */
+ rc = gsm48_cc_tx_simple(msg->lchan, GSM48_MT_CC_CONNECT_ACK);
+ break;
+ case GSM48_MT_CC_CONNECT_ACK:
+ /* MO: Answer to CONNECT */
+ call->state = GSM_CSTATE_ACTIVE;
+ DEBUGP(DCC, "CONNECT_ACK (state->ACTIVE)\n");
+ break;
+ case GSM48_MT_CC_RELEASE:
+ DEBUGP(DCC, "RELEASE\n");
+ /* need to respond with RELEASE_COMPLETE */
+ break;
+ case GSM48_MT_CC_STATUS_ENQ:
+ rc = gsm48_cc_rx_status_enq(msg);
+ break;
+ case GSM48_MT_CC_DISCONNECT:
+ /* Section 5.4.3.2 */
+ DEBUGP(DCC, "DISCONNECT (state->RELEASE_REQ)\n");
+ call->state = GSM_CSTATE_RELEASE_REQ;
+ /* FIXME: clear the network connection */
+ rc = gsm48_cc_tx_simple(msg->lchan, GSM48_MT_CC_RELEASE);
+ break;
+ case GSM48_MT_CC_SETUP:
+ call->type = GSM_CT_MO;
+ call->state = GSM_CSTATE_INITIATED;
+ call->transaction_id = gh->proto_discr & 0xf0;
+ DEBUGP(DCC, "SETUP(tid=0x%02x)\n", call->transaction_id);
+ rc = gsm48_cc_tx_simple(msg->lchan, GSM48_MT_CC_CONNECT);
+ /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
+ break;
+ case GSM48_MT_CC_EMERG_SETUP:
+ DEBUGP(DCC, "EMERGENCY SETUP\n");
+ /* FIXME: continue with CALL_PROCEEDING, ALERTING, CONNECT, RELEASE_COMPLETE */
+ break;
+ default:
+ fprintf(stderr, "Unimplemented GSM 04.08 msg type 0x%02x\n",
+ msg_type);
+ break;
+ }
+
+ return rc;
+}
+
/* here we pass in a msgb from the RSL->RLL. We expect the l3 pointer to be set */
int gsm0408_rcvmsg(struct msgb *msg)
{