Work on message handling of layer 3.
authorAndreas Eversberg <jolly@eversberg.eu>
Fri, 2 Apr 2010 06:28:08 +0000 (08:28 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Fri, 2 Apr 2010 06:28:08 +0000 (08:28 +0200)
src/host/gsm48-andreas/README
src/host/gsm48-andreas/gsm48_cc.c
src/host/gsm48-andreas/gsm48_l3.h
src/host/gsm48-andreas/gsm48_mm.c
src/host/gsm48-andreas/gsm48_rr.c
src/host/gsm48-andreas/support.h

index fa238ae..c06e735 100644 (file)
@@ -17,17 +17,20 @@ process                             CC              complete
 message format                 CC              incomplete
 (messages are currently totally wrong)
 state machine                  CC              complete
+debugging                      CC              
 
 common procedures              MM              (almost) complete
 specific procedures            MM              incomplete
 connection management          MM              incomplete
 state machine                  MM              incomplete
 support functions              MM              incomplete
+debugging                      MM              
 
 system information (1-6)       RR              complete
 connection establishment       RR              (almost) complete
 connection release             RR              ??
 dedicated mode                 RR              incomplete
+debugging                      RR              
 
 idle mode PLMN selection       MM(03.22)       complete
 idle mode cell selection       MM(03.22)       complete
index 03f8294..f2933a1 100644 (file)
@@ -1,17 +1,3 @@
-fragen:
-
-warum ist layer 2 ein socket client
-wo soll layer 3 hin
-wo soll die app (layer 4) liegen, in der lib oder im con
-transactions wie im openbsc
-lchan in einer msg?: eine 1:1 beziehung zwischen ms und lchan?:
-ms instanzliste für mehrere geräte, 'name' fuer ein jedes geraet
-messages wie bei openbsc
-ist der tlv-parser bufferoverflow-safe?: was ist mit dem letzten ie?: sollte der parser nicht error zurücklifern und dann den aufrufenden prozess beenden?:
-wieso ist classmark1 in gsm_04_08.h MSB und nicht LSB wie sonst?:
-headerkonzept für inter-layer und interface
-
-
 /*
  * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
  *
@@ -33,14 +19,23 @@ headerkonzept für inter-layer und interface
  *
  */
 
-/* QUICK OVERVIEW:
- *
- * - support functions and data
- * - handlers for messages to lower layer (gsm48_cc_tx_*)
- * - state machine for MNCC messages
- * - handlers for messages from lower layer (gsm48_cc_rx_*)
- * - state machine for lower layer messages
- * - timeout handler
+todo: on CM service request
+establish request before sending setup (queue setup message)
+on timeout (t303): handle as required
+on establish confirm: send setup
+se establishment cause, if required
+on reject request from lower layer: handle as required
+on release request from upper layer: handle as required
+
+todo: on establish indication
+process the first message as if it is a data indication
+
+todo: handle all other MMCC primitives
+
+todo: finish message handling
+
+/*
+ * timers
  */
 
 /* start various timers */
@@ -64,6 +59,29 @@ static void gsm48_stop_cc_timer(struct gsm_trans *trans)
        }
 }
 
+/*
+ * messages
+ */
+
+/* push MMCC header and send to MM */
+static int gsm48_cc_to_mm(struct msgb *msg, struct gsm_trans *trans, int msg_type)
+{
+       struct osmocom_ms *ms = trans->ms;
+       struct gsm48_mmxx_hdr *mmh;
+
+       /* push RR header */
+       msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+       mmh = (struct gsm48_mmxx_hdr *)msg->data;
+       mmh->msg_type = msg_type;
+
+       /* send message to MM */
+       return gsm48_mmxx_downmsg(ms, msg);
+}
+
+/*
+ * process handlers
+ */
+
 /* send release indication to upper layer */
 int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
                     u_int32_t callref, int location, int value)
@@ -79,33 +97,45 @@ int mncc_release_ind(struct gsm_network *net, struct gsm_trans *trans,
 /* sending status message in response to unknown message */
 static int gsm48_cc_tx_status(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
        u_int8_t *cause, *call_state;
 
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
+
        gh->msg_type = GSM48_MT_CC_STATUS;
 
-       cause = msgb_put(msg, 3);
+       cause = msgb_put(nmsg, 3);
        cause[0] = 2;
-im openbsc muss LOC_PRIV_LOC_U verwendet werden !!!!
-       cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_USER;
+       cause[1] = GSM48_CAUSE_CS_GSM | GSM48_CAUSE_LOC_PRN_S_LU;
        cause[2] = 0x80 | 30;   /* response to status inquiry */
 
-       call_state = msgb_put(msg, 1);
+       call_state = msgb_put(nmsg, 1);
        call_state[0] = 0xc0 | 0x00;
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
+
+complete
+------------------------------------------------------------------------------
+incomplete
+
 /* setup message from upper layer */
 static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
+       struct msgb *nmsg;
        struct gsm48_hdr *gh;
        struct gsm_mncc *setup = arg;
        int rc, trans_id;
 
-       gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        /* transaction id must not be assigned */
        if (trans->transaction_id != 0xff) { /* unasssigned */
@@ -113,8 +143,6 @@ static int gsm48_cc_tx_setup(struct gsm_trans *trans, void *arg)
                        "This is not allowed!\n");
                /* Temporarily out of order */
                rc = mncc_release_ind(trans->subscr->net, trans, trans->callref,
-alle PRN_S_LU nach USER !!!!
-auch beim LCR für ms-mode anpassen !!!!
                                      GSM48_CAUSE_LOC_PRN_S_LU,
                                      GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
                trans->callref = 0;
@@ -140,53 +168,64 @@ auch beim LCR für ms-mode anpassen !!!!
        gsm48_start_cc_timer(trans, 0x303, GSM48_T303_MO);
 
        /* bearer capability */
-       gsm48_encode_bearer_cap(msg, 0, &setup->bearer_cap);
+       gsm48_encode_bearer_cap(nmsg, 0, &setup->bearer_cap);
        /* facility */
        if (setup->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &setup->facility);
+               gsm48_encode_facility(nmsg, 0, &setup->facility);
        /* called party BCD number */
        if (setup->fields & MNCC_F_CALLED)
-               gsm48_encode_called(msg, &setup->called);
+               gsm48_encode_called(nmsg, &setup->called);
        /* user-user */
        if (setup->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &setup->useruser);
+               gsm48_encode_useruser(nmsg, 0, &setup->useruser);
        /* ss version */
        if (setup->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &setup->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &setup->ssversion);
        /* CLIR suppression */
        if (setup->clir.sup)
-               gsm48_encode_clir_sup(msg);
+               gsm48_encode_clir_sup(nmsg);
        /* CLIR invocation */
        if (setup->clir.inv)
-               gsm48_encode_clir_inv(msg);
+               gsm48_encode_clir_inv(nmsg);
        /* cc cap */
        if (setup->fields & MNCC_F_CCCAP)
-               gsm48_encode_cccap(msg, 0, &setup->cccap);
+               gsm48_encode_cccap(nmsg, 0, &setup->cccap);
 
+       /* actually MM CONNECTION PENDING */
        new_cc_state(trans, GSM_CSTATE_CALL_INITIATED);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_EST_REQ);
 }
 
 /* connect ack message from upper layer */
 static int gsm48_cc_tx_connect_ack(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_CONNECT_ACK;
 
        new_cc_state(trans, GSM_CSTATE_ACTIVE);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* call conf message from upper layer */
 static int gsm48_cc_tx_call_conf(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *confirm = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_CALL_CONF;
 
@@ -195,47 +234,57 @@ diesen state in MT_CALL_CONF umbenennen !!!!
 
        /* bearer capability */
        if (confirm->fields & MNCC_F_BEARER_CAP)
-               gsm48_encode_bearer_cap(msg, 0, &confirm->bearer_cap);
+               gsm48_encode_bearer_cap(nmsg, 0, &confirm->bearer_cap);
        /* cause */
        if (confirm->fields & MNCC_F_CAUSE)
-               gsm48_encode_cause(msg, 0, &confirm->cause);
+               gsm48_encode_cause(nmsg, 0, &confirm->cause);
        /* cc cap */
        if (confirm->fields & MNCC_F_CCCAP)
-               gsm48_encode_cccap(msg, 0, &confirm->cccap);
+               gsm48_encode_cccap(nmsg, 0, &confirm->cccap);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* alerting message from upper layer */
 static int gsm48_cc_tx_alerting(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *alerting = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_ALERTING;
 
        /* facility */
        if (alerting->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &alerting->facility);
+               gsm48_encode_facility(nmsg, 0, &alerting->facility);
        /* user-user */
        if (alerting->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &alerting->useruser);
+               gsm48_encode_useruser(nmsg, 0, &alerting->useruser);
        /* ss version */
        if (alerting->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &alerting->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &alerting->ssversion);
 
        new_cc_state(trans, GSM_CSTATE_CALL_RECEIVED);
        
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* connect message from upper layer */
 static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *connect = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_CONNECT;
 
@@ -244,88 +293,118 @@ static int gsm48_cc_tx_connect(struct gsm_trans *trans, void *arg)
 
        /* facility */
        if (connect->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &connect->facility);
+               gsm48_encode_facility(nmsg, 0, &connect->facility);
        /* user-user */
        if (connect->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &connect->useruser);
+               gsm48_encode_useruser(nmsg, 0, &connect->useruser);
        /* ss version */
        if (connect->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &connect->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &connect->ssversion);
 
        new_cc_state(trans, GSM_CSTATE_CONNECT_REQUEST);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* notify message from upper layer */
 static int gsm48_cc_tx_notify(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *notify = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_NOTIFY;
 
        /* notify */
-       gsm48_encode_notify(msg, notify->notify);
+       gsm48_encode_notify(nmsg, notify->notify);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* start dtmf message from upper layer */
 static int gsm48_cc_tx_start_dtmf(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *dtmf = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_START_DTMF;
 
        /* keypad */
-       gsm48_encode_keypad(msg, dtmf->keypad);
+       gsm48_encode_keypad(nmsg, dtmf->keypad);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* stop dtmf message from upper layer */
 static int gsm48_cc_tx_stop_dtmf(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_STOP_DTMF;
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* hold message from upper layer */
 static int gsm48_cc_tx_hold(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_HOLD;
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* retrieve message from upper layer */
 static int gsm48_cc_tx_hold(struct gsm_trans *trans, void *arg)
 {
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_RETRIEVE;
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* disconnect message from upper layer or from timer event */
 static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *disc = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_DISCONNECT;
 
@@ -334,34 +413,39 @@ static int gsm48_cc_tx_disconnect(struct gsm_trans *trans, void *arg)
 
        /* cause */
        if (disc->fields & MNCC_F_CAUSE)
-               gsm48_encode_cause(msg, 1, &disc->cause);
+               gsm48_encode_cause(nmsg, 1, &disc->cause);
        else
-               gsm48_encode_cause(msg, 1, &default_cause);
+               gsm48_encode_cause(nmsg, 1, &default_cause);
 
        /* facility */
        if (disc->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &disc->facility);
+               gsm48_encode_facility(nmsg, 0, &disc->facility);
        /* progress */
        if (disc->fields & MNCC_F_PROGRESS)
-               gsm48_encode_progress(msg, 0, &disc->progress);
+               gsm48_encode_progress(nmsg, 0, &disc->progress);
        /* user-user */
        if (disc->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &disc->useruser);
+               gsm48_encode_useruser(nmsg, 0, &disc->useruser);
        /* ss version */
        if (disc->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &disc->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &disc->ssversion);
 
        new_cc_state(trans, GSM_CSTATE_DISCONNECT_REQ);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* release message from upper layer or from timer event */
 static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *rel = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_RELEASE;
 
@@ -372,16 +456,16 @@ static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
 
        /* cause */
        if (rel->fields & MNCC_F_CAUSE)
-               gsm48_encode_cause(msg, 0, &rel->cause);
+               gsm48_encode_cause(nmsg, 0, &rel->cause);
        /* facility */
        if (rel->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &rel->facility);
+               gsm48_encode_facility(nmsg, 0, &rel->facility);
        /* user-user */
        if (rel->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &rel->useruser);
+               gsm48_encode_useruser(nmsg, 0, &rel->useruser);
        /* ss version */
        if (rel->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &rel->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &rel->ssversion);
 
        trans->cc.T308_second = 0;
        memcpy(&trans->cc.msg, rel, sizeof(struct gsm_mncc));
@@ -389,15 +473,21 @@ static int gsm48_cc_tx_release(struct gsm_trans *trans, void *arg)
        if (trans->cc.state != GSM_CSTATE_RELEASE_REQ)
                new_cc_state(trans, GSM_CSTATE_RELEASE_REQ);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* reject message from upper layer or from timer event */
 static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *rel = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_mmxx_hdr *mmh;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_RELEASE_COMPL;
 
@@ -407,112 +497,150 @@ static int gsm48_cc_tx_release_compl(struct gsm_trans *trans, void *arg)
 
        /* cause */
        if (rel->fields & MNCC_F_CAUSE)
-               gsm48_encode_cause(msg, 0, &rel->cause);
+               gsm48_encode_cause(nmsg, 0, &rel->cause);
        /* facility */
        if (rel->fields & MNCC_F_FACILITY)
-               gsm48_encode_facility(msg, 0, &rel->facility);
+               gsm48_encode_facility(nmsg, 0, &rel->facility);
        /* user-user */
        if (rel->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 0, &rel->useruser);
+               gsm48_encode_useruser(nmsg, 0, &rel->useruser);
        /* ss version */
        if (rel->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &rel->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &rel->ssversion);
 
-       trans_free(trans);
 
-       return gsm48_sendmsg(msg, trans);
+       gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
+
+       /* release MM connection */
+       nmsg = gsm48_mmxx_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       mmh = (struct gsm48_mmxx_hdr *)nmsg->data;
+       mmh->msg_type = GSM48_MMCC_REL_REQ;
+       mmh->cause = **todo
+       gsm48_mmxx_downmsg(ms, nmsg);
+
+       new_cc_state(trans, GSM_CSTATE_NULL);
+
+       trans->callref = 0;
+       trans_free(trans);
 }
 
 /* facility message from upper layer or from timer event */
 static int gsm48_cc_tx_facility(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *fac = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_FACILITY;
 
        /* facility */
-       gsm48_encode_facility(msg, 1, &fac->facility);
+       gsm48_encode_facility(nmsg, 1, &fac->facility);
        /* ss version */
        if (rel->fields & MNCC_F_SSVERSION)
-               gsm48_encode_ssversion(msg, 0, &rel->ssversion);
+               gsm48_encode_ssversion(nmsg, 0, &rel->ssversion);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* user info message from upper layer or from timer event */
 static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *user = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_USER_INFO;
 
        /* user-user */
        if (user->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 1, &user->useruser);
+               gsm48_encode_useruser(nmsg, 1, &user->useruser);
        /* more data */
        if (user->more)
-               gsm48_encode_more(msg);
+               gsm48_encode_more(nmsg);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* modify message from upper layer or from timer event */
 static int gsm48_cc_tx_modify(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *modify = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_MODIFY;
 
        gsm48_start_cc_timer(trans, 0x323, GSM48_T323_MS);
 
        /* bearer capability */
-       gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
+       gsm48_encode_bearer_cap(nmsg, 1, &modify->bearer_cap);
 
        new_cc_state(trans, GSM_CSTATE_MO_TERM_MODIFY);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* modify complete message from upper layer or from timer event */
 static int gsm48_cc_tx_modify_complete(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *modify = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_MODIFY_COMPL;
 
        /* bearer capability */
-       gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
+       gsm48_encode_bearer_cap(nmsg, 1, &modify->bearer_cap);
 
        new_cc_state(trans, GSM_CSTATE_ACTIVE);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* modify reject message from upper layer or from timer event */
 static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
 {
        struct gsm_mncc *modify = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+       struct msgb *nmsg;
+       struct gsm48_hdr *gh;
+
+       nmsg = gsm48_l3_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh));
 
        gh->msg_type = GSM48_MT_CC_MODIFY_REJECT;
 
        /* bearer capability */
-       gsm48_encode_bearer_cap(msg, 1, &modify->bearer_cap);
+       gsm48_encode_bearer_cap(nmsg, 1, &modify->bearer_cap);
        /* cause */
-       gsm48_encode_cause(msg, 1, &modify->cause);
+       gsm48_encode_cause(nmsg, 1, &modify->cause);
 
        new_cc_state(trans, GSM_CSTATE_ACTIVE);
 
-       return gsm48_sendmsg(msg, trans);
+       return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
 }
 
 /* state trasitions for MNCC messages (upper layer) */
@@ -652,7 +780,7 @@ static int gsm48_cc_rx_alerting(struct gsm_trans *trans, struct msgb *msg)
        /* user-user */
        if (TLVP_PRESENT(&tp, GSM48_IE_USER_USER)) {
                alerting.fields |= MNCC_F_USERUSER;
-               gsm48_decode_useruser(&alerting.alerting,
+               gsm48_decode_useruser(&alerting.useruser,
                                TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
        }
 
@@ -1006,6 +1134,8 @@ static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
        unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
        struct tlv_parsed tp;
        struct gsm_mncc rel;
+       struct msgb *nmsg;
+       struct gsm48_mmxx_hdr *mmh;
        int rc;
 
        gsm48_stop_cc_timer(trans);
@@ -1042,6 +1172,15 @@ static int gsm48_cc_rx_release(struct gsm_trans *trans, struct msgb *msg)
                rc = mncc_recvmsg(trans->subscr->net, trans, MNCC_REL_IND, &rel);
        }
 
+       /* release MM connection */
+       nmsg = gsm48_mmxx_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       mmh = (struct gsm48_mmxx_hdr *)nmsg->data;
+       mmh->msg_type = GSM48_MMCC_REL_REQ;
+       mmh->cause = **todo
+       gsm48_mmxx_downmsg(ms, nmsg);
+
        new_cc_state(trans, GSM_CSTATE_NULL);
 
        trans->callref = 0;
@@ -1057,6 +1196,8 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
        unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
        struct tlv_parsed tp;
        struct gsm_mncc rel;
+       struct msgb *nmsg;
+       struct gsm48_mmxx_hdr *mmh;
        int rc = 0;
 
        gsm48_stop_cc_timer(trans);
@@ -1102,6 +1243,17 @@ static int gsm48_cc_rx_release_compl(struct gsm_trans *trans, struct msgb *msg)
                }
        }
 
+       /* release MM connection */
+       nmsg = gsm48_mmxx_msgb_alloc();
+       if (!nmsg)
+               return -ENOMEM;
+       mmh = (struct gsm48_mmxx_hdr *)nmsg->data;
+       mmh->msg_type = GSM48_MMCC_REL_REQ;
+       mmh->cause = **todo
+       gsm48_mmxx_downmsg(ms, nmsg);
+
+       new_cc_state(trans, GSM_CSTATE_NULL);
+
        trans->callref = 0;
        trans_free(trans);
 
@@ -1117,33 +1269,38 @@ static int gsm48_cc_rx_facility(struct gsm_trans *trans, struct msgb *msg)
 
        memset(&fac, 0, sizeof(struct gsm_mncc));
        fac.callref = trans->callref;
-       /* facility */
        if (payload_len < 1) {
                DEBUGP(DCC, "Short read of facility message error.\n");
                return -EINVAL;
        }
+       /* facility */
        gsm48_decode_facility(&fac.facility, gh->data);
 
        return mncc_recvmsg(trans->subscr->net, trans, MNCC_FACILITY_IND, &fac);
 }
 
 /* user info is received from lower layer */
-static int gsm48_cc_tx_userinfo(struct gsm_trans *trans, void *arg)
+static int gsm48_cc_rx_userinfo(struct gsm_trans *trans, void *arg)
 {
-       struct gsm_mncc *user = arg;
-       struct msgb *msg = gsm48_msgb_alloc();
-       struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
-
-       gh->msg_type = GSM48_MT_CC_USER_INFO;
+       struct gsm48_hdr *gh = msgb_l3(msg);
+       unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
+       struct gsm_mncc user;
 
+       memset(&user, 0, sizeof(struct gsm_mncc));
+       user.callref = trans->callref;
+       if (payload_len < 1) {
+               DEBUGP(DCC, "Short read of userinfo message error.\n");
+               return -EINVAL;
+       }
+       tlv_parse(&tp, &rsl_att_tlvdef, gh->data, payload_len, GSM48_IE_USERUSER, 0);
        /* user-user */
-       if (user->fields & MNCC_F_USERUSER)
-               gsm48_encode_useruser(msg, 1, &user->useruser);
+       gsm48_decode_useruser(&user.useruser,
+                       TLVP_VAL(&tp, GSM48_IE_USER_USER)-1);
        /* more data */
-       if (user->more)
-               gsm48_encode_more(msg);
+       if (TLVP_PRESENT(&tp, GSM48_IE_MORE))
+               user.more = 1;
 
-       return gsm48_sendmsg(msg, trans);
+       return mncc_recvmsg(trans->subscr->net, trans, MNCC_USERINFO_IND, &userinfo);
 }
 
 /* modify is received from lower layer */
@@ -1160,6 +1317,7 @@ static int gsm48_cc_rx_modify(struct gsm_trans *trans, struct msgb *msg)
                DEBUGP(DCC, "Short read of modify message error.\n");
                return -EINVAL;
        }
+       /* bearer capability */
        gsm48_decode_bearer_cap(&modify.bearer_cap, gh->data);
 
        new_cc_state(trans, GSM_CSTATE_MO_ORIG_MODIFY);
@@ -1183,6 +1341,7 @@ static int gsm48_cc_rx_modify_complete(struct gsm_trans *trans, struct msgb *msg
                DEBUGP(DCC, "Short read of modify complete message error.\n");
                return -EINVAL;
        }
+       /* bearer capability */
        gsm48_decode_bearer_cap(&modify.bearer_cap, gh->data);
 
        new_cc_state(trans, GSM_CSTATE_ACTIVE);
@@ -1287,6 +1446,43 @@ static struct datastate {
 #define DATASLLEN \
        (sizeof(datastatelist) / sizeof(struct datastate))
 
+static int gsm48_mmcc_data_ind(struct gsm_trans *trans, struct msgb *msg)
+{
+       struct osmocom_ms *ms = trans->ms;
+       struct gsm48_hdr *gh = msgb_l3(msg);
+       int msg_type = gh->msg_type & 0xbf;
+
+       /* pull the MMCC header */
+       msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr));
+
+       DEBUGP(DMM, "(ms %s) Received '%s' in CC state %s\n", ms->name,
+               gsm48_cc_msg_name(msg_type), gsm48_cc_state_names[trans->state]);
+
+       /* find function for current state and message */
+       for (i = 0; i < MMDATASLLEN; i++)
+               if ((msg_type == datastatelist[i].type)
+                && ((1 << trans->state) & datastatelist[i].states))
+                       break;
+       if (i == MMDATASLLEN) {
+               DEBUGP(DMM, "Message unhandled at this state.\n");
+               return 0;
+       }
+
+       rc = datastatelist[i].rout(trans, msg);
+
+       return rc;
+}
+
+/* state trasitions for call control messages (lower layer) */
+static struct mmxxstate {
+       u_int32_t       states;
+       int             type;
+       int             (*rout) (struct gsm_trans *trans, struct msgb *msg);
+} mmxxstatelist[] = {
+what?: {SBIT(GSM_CSTATE_ACTIVE),
+        GSM48_MT_CC_MODIFY, gsm48_cc_rx_modify},
+};
+
 
 /* timeout events of all timers */
 static void gsm48_cc_timeout(void *arg)
@@ -1294,11 +1490,14 @@ static void gsm48_cc_timeout(void *arg)
        struct gsm_trans *trans = arg;
        int disconnect = 0, release = 0;
        int mo_cause = GSM48_CC_CAUSE_RECOVERY_TIMER;
-im openbsc muss LOC_PRIV_LOC_U verwendet werden !!!!
-       int mo_location = GSM48_CAUSE_LOC_USER;
+** openbsc must use LOC_PRIV_LOC_U on protocol side or network (maybe some cfg option)
+** auch beim LCR für ms-mode anpassen !!!!
+       int mo_location = GSM48_CAUSE_LOC_PRN_S_LU;
        int l4_cause = GSM48_CC_CAUSE_NORMAL_UNSPEC;
        int l4_location = GSM48_CAUSE_LOC_PRN_S_LU;
        struct gsm_mncc mo_rel, l4_rel;
+       struct msgb *nmsg;
+       struct gsm48_mmxx_hdr *mmh;
 
        memset(&mo_rel, 0, sizeof(struct gsm_mncc));
        mo_rel.callref = trans->callref;
@@ -1322,6 +1521,18 @@ im openbsc muss LOC_PRIV_LOC_U verwendet werden !!!!
                        trans->cc.T308_second = 1;
                        break; /* stay in release state */
                }
+               /* release MM connection */
+               nmsg = gsm48_mmxx_msgb_alloc();
+               if (!nmsg)
+                       return -ENOMEM;
+               mmh = (struct gsm48_mmxx_hdr *)nmsg->data;
+               mmh->msg_type = GSM48_MMCC_REL_REQ;
+               mmh->cause = **todo
+               gsm48_mmxx_downmsg(ms, nmsg);
+
+               new_cc_state(trans, GSM_CSTATE_NULL);
+
+               trans->callref = 0;
                trans_free(trans);
                return;
        case 0x310:
index 4c0751b..d15887a 100644 (file)
@@ -143,21 +143,11 @@ struct gsm48_mmxx_hdr {
 #define GSM48_MMR_ST_UPDATED           2
 
 /* GSM 04.07 9.2.1 */
-#define GSM48_MMCC_ST_IDLE             0
-#define GSM48_MMCC_ST_CONN_PEND                1
-#define GSM48_MMCC_ST_DEDICATED                2
-#define GSM48_MMCC_ST_CONN_SUSP                3
-#define GSM48_MMCC_ST_REESTPEND                4
-#define GSM48_MMSS_ST_IDLE             0
-#define GSM48_MMSS_ST_CONN_PEND                1
-#define GSM48_MMSS_ST_DEDICATED                2
-#define GSM48_MMSS_ST_CONN_SUSP                3
-#define GSM48_MMSS_ST_REESTPEND                4
-#define GSM48_MMSMS_ST_IDLE            0
-#define GSM48_MMSMS_ST_CONN_PEND       1
-#define GSM48_MMSMS_ST_DEDICATED       2
-#define GSM48_MMSMS_ST_CONN_SUSP       3
-#define GSM48_MMSMS_ST_REESTPEND       4
+#define GSM48_MMXX_ST_IDLE             0
+#define GSM48_MMXX_ST_CONN_PEND                1
+#define GSM48_MMXX_ST_DEDICATED                2
+#define GSM48_MMXX_ST_CONN_SUSP                3
+#define GSM48_MMXX_ST_REESTPEND                4
 
 /* GSM 04.08 4.1.2.1 */
 #define        GSM48_MM_ST_NULL                0
index abd57a0..5973ee7 100644 (file)
  * messages
  */
 
+/* names of MMxx-SAP */
+static const struct value_string gsm48_mmxx_msg_names[] = {
+       { GSM48_MMCC_EST_REQ,           "MMCC_EST_REQ" },
+       { GSM48_MMCC_EST_IND,           "MMCC_EST_IND" },
+       { GSM48_MMCC_EST_CNF,           "MMCC_EST_CNF" },
+       { GSM48_MMCC_REL_REQ,           "MMCC_REL_REQ" },
+       { GSM48_MMCC_REL_IND,           "MMCC_REL_IND" },
+       { GSM48_MMCC_DATA_REQ,          "MMCC_DATA_REQ" },
+       { GSM48_MMCC_DATA_IND,          "MMCC_DATA_IND" },
+       { GSM48_MMCC_UNIT_DATA_REQ,     "MMCC_UNIT_DATA_REQ" },
+       { GSM48_MMCC_UNIT_DATA_IND,     "MMCC_UNIT_DATA_IND" },
+       { GSM48_MMCC_SYNC_IND,          "MMCC_SYNC_IND" },
+       { GSM48_MMCC_REEST_REQ,         "MMCC_REEST_REQ" },
+       { GSM48_MMCC_REEST_CNF,         "MMCC_REEST_CNF" },
+       { GSM48_MMCC_ERR_IND,           "MMCC_ERR_IND" },
+       { GSM48_MMCC_PROMPT_IND,        "MMCC_PROMPT_IND" },
+       { GSM48_MMCC_PROMPT_REJ,        "MMCC_PROMPT_REJ" },
+       { GSM48_MMSS_EST_REQ,           "MMSS_EST_REQ" },
+       { GSM48_MMSS_EST_IND,           "MMSS_EST_IND" },
+       { GSM48_MMSS_EST_CNF,           "MMSS_EST_CNF" },
+       { GSM48_MMSS_REL_REQ,           "MMSS_REL_REQ" },
+       { GSM48_MMSS_REL_IND,           "MMSS_REL_IND" },
+       { GSM48_MMSS_DATA_REQ,          "MMSS_DATA_REQ" },
+       { GSM48_MMSS_DATA_IND,          "MMSS_DATA_IND" },
+       { GSM48_MMSS_UNIT_DATA_REQ,     "MMSS_UNIT_DATA_REQ" },
+       { GSM48_MMSS_UNIT_DATA_IND,     "MMSS_UNIT_DATA_IND" },
+       { GSM48_MMSS_REEST_REQ,         "MMSS_REEST_REQ" },
+       { GSM48_MMSS_REEST_CNF,         "MMSS_REEST_CNF" },
+       { GSM48_MMSS_ERR_IND,           "MMSS_ERR_IND" },
+       { GSM48_MMSS_PROMPT_IND,        "MMSS_PROMPT_IND" },
+       { GSM48_MMSS_PROMPT_REJ,        "MMSS_PROMPT_REJ" },
+       { GSM48_MMSMS_EST_REQ,          "MMSMS_EST_REQ" },
+       { GSM48_MMSMS_EST_IND,          "MMSMS_EST_IND" },
+       { GSM48_MMSMS_EST_CNF,          "MMSMS_EST_CNF" },
+       { GSM48_MMSMS_REL_REQ,          "MMSMS_REL_REQ" },
+       { GSM48_MMSMS_REL_IND,          "MMSMS_REL_IND" },
+       { GSM48_MMSMS_DATA_REQ,         "MMSMS_DATA_REQ" },
+       { GSM48_MMSMS_DATA_IND,         "MMSMS_DATA_IND" },
+       { GSM48_MMSMS_UNIT_DATA_REQ,    "MMSMS_UNIT_DATA_REQ" },
+       { GSM48_MMSMS_UNIT_DATA_IND,    "MMSMS_UNIT_DATA_IND" },
+       { GSM48_MMSMS_REEST_REQ,        "MMSMS_REEST_REQ" },
+       { GSM48_MMSMS_REEST_CNF,        "MMSMS_REEST_CNF" },
+       { GSM48_MMSMS_ERR_IND,          "MMSMS_ERR_IND" },
+       { GSM48_MMSMS_PROMPT_IND,       "MMSMS_PROMPT_IND" },
+       { GSM48_MMSMS_PROMPT_REJ,       "MMSMS_PROMPT_REJ" },
+       { 0,                            NULL }
+};
+
+const char *get_mmxx_name(int value)
+{
+       return get_value_string(gsm48_mmxx_msg_names, value);
+}
+
 /* allocate GSM 04.08 message (MMxx-SAP) */
 static struct msgb *gsm48_mmxx_msgb_alloc(void)
 {
@@ -87,19 +140,15 @@ int gsm48_rr_dequeue(struct osmocom_ms *ms)
        return work;
 }
 
-tomorrow:
-finish this function
-check names
-do msg for MMxx
-do msg in call control
-
-
 /* push RR header and send to RR */
 static int gsm48_mm_to_rr(ms, msg, int msg_type)
 {
-       1. push header
-       2. add msg_type
+       /* push RR header */
+       msgb_push(msg, sizeof(struct gsm48_rr_hdr));
+       rrh = (struct gsm48_rr_hdr *)msg->data;
+       rrh->msg_type = msg_type;
 
+       /* send message to RR */
        return gsm48_rr_downmsg(ms, msg);
 }
 
@@ -107,15 +156,65 @@ static int gsm48_mm_to_rr(ms, msg, int msg_type)
  * state transition
  */
 
+static const char *gsm48_mm_state_names[] = {
+       "NULL",
+       "undefined 1",
+       "undefined 2",
+       "LOC_UPD_INIT",
+       "undefined 4",
+       "WAIT_OUT_MM_CONN",
+       "MM_CONN_ACTIVE",
+       "IMSI_DETACH_INIT",
+       "PROCESS_CM_SERV_P",
+       "WAIT_NETWORK_CMD",
+       "LOC_UPD_REJ",
+       "undefined 11",
+       "undefined 12",
+       "WAIT_RR_CONN_LUPD",
+       "WAIT_RR_CONN_MM_CON",
+       "WAIT_RR_CONN_IMSI_D",
+       "undefined 16",
+       "WAIT_REEST",
+       "WAIT_RR_ACTIVE",
+       "MM_IDLE",
+       "WAIT_ADD_OUT_MM_CON",
+       "MM_CONN_ACTIVE_VGCS",
+       "WAIT_RR_CONN_VGCS",
+       "LOC_UPD_PEND",
+       "IMSI_DETACH_PEND",
+       "RR_CONN_RELEASE_NA"
+};
+
+static const char *gsm48_mm_substate_names[] = {
+       "NORMAL_SERVICE",
+       "ATTEMPT_UPDATE",
+       "LIMITED_SERVICE",
+       "NO_IMSI",
+       "NO_CELL_AVAIL",
+       "LOC_UPD_NEEDED",
+       "PLMN_SEARCH",
+       "PLMN_SEARCH_NORMAL",
+       "RX_VGCS_NORMAL",
+       "RX_VGCS_LIMITED"
+};
+
+static const char *gsm48_mmxx_state_names[] = {
+       "IDLE",
+       "CONN_PEND",
+       "DEDICATED",
+       "CONN_SUSP",
+       "REESTPEND"
+};
+
 /* Set new MM state, also new substate in case of MM IDLE state. */
 static void new_mm_state(struct gsm48_mmlayer *mm, int state, int substate)
 {
-       DEBUGP(DMM, "(ms %s) new state %s", mm->ms, mm_state_names[mm->state]);
+       DEBUGP(DMM, "(ms %s) new state %s", mm->ms, gsm48_mm_state_names[mm->state]);
        if (mm->state == GSM48_MM_ST_MM_ILDE)
-               DEBUGP(DMM, " substate %s", mm_substate_names[mm->substate]);
+               DEBUGP(DMM, " substate %s", gsm48_mm_substate_names[mm->substate]);
        DEBUGP(DMM, "-> %s", mm_state_names[state]);
        if (state == GSM48_MM_ST_MM_ILDE)
-               DEBUGP(DMM, " substate %s", mm_substate_names[substate]);
+               DEBUGP(DMM, " substate %s", gsm48_mm_substate_names[substate]);
        DEBUGP(DMM, "\n");
 
        mm->state = state;
@@ -221,6 +320,7 @@ static int gsm48_mm_tx_mm_status(struct osmocom_ms *ms, u_int8_t reject)
        gh->msg_type = GSM48_MT_MM_STATUS;
        *reject_cause = reject;
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -238,6 +338,7 @@ static int gsm48_mm_tx_tmsi_reall_cpl(struct osmocom_ms *ms)
        gh->proto_discr = GSM48_PDISC_MM;
        gh->msg_type = GSM48_MT_MM_TMSI_REALL_COMPL;
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -334,6 +435,7 @@ static int gsm48_mm_tx_auth_rsp(struct osmocom_ms *ms, struct gsm48_mmevent *ev)
        /* SRES */
        memcpy(sres, ev->sres, 4);
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -416,6 +518,7 @@ static int gsm48_mm_tx_id_rsp(struct osmocom_ms *ms, u_int8_t mi_type)
        /* MI */
        gsm48_encode_mi(nmsg, subscr, mi_type);
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -441,6 +544,7 @@ static int gsm48_mm_tx_imsi_detach(struct osmocom_ms *ms, int rr_prim)
        /* MI */
        gsm48_encode_mi(nmsg, subscr, mi_type);
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, rr_prim);
 }
 
@@ -702,6 +806,7 @@ static int gsm48_mm_tx_cm_serv_req(struct osmocom_ms *ms, void *arg)
        gsm48_encode_mi(nmsg, subscr, mi_type);
        /* prio is optional for eMLPP */
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_EST_REQ);
 }
 
@@ -715,6 +820,7 @@ static int gsm48_mm_tx_cm_service_abort(struct osmocom_ms *ms, void *arg)
        gh->proto_discr = GSM48_PDISC_MM;
        gh->msg_type = GSM48_MT_MM_CM_SERV_ABORT;
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -746,6 +852,7 @@ static int gsm48_mm_tx_cm_reest_req(struct osmocom_ms *ms, void *arg)
                memcpy(ie, buf, 1 + sizeof(struct gsm48_loc_area_id));
        }
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR__REQ);
 }
 
@@ -902,73 +1009,36 @@ static int gsm48_mm_classm_chg(struct osmocom_ms *ms, void *arg)
        gsm_rr_tx_cm_change(sm, abort, RR_ABORT_REQ);
 }
 
-/* state trasitions for mobile managemnt messages (upper layer / events) */
-static struct eventstate {
+/* state trasitions for MMxx-SAP messages from upper layers */
+static struct downstate {
        u_int32_t       states;
        u_int32_t       substates;
        int             type;
        int             (*rout) (struct osmocom_ms *ms, struct msgb *msg);
-} eventstatelist[] = {
+} downstatelist[] = {
        /* 4.2.2.1 Normal service */
-** todo: check if there is a senders of every event
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
         MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
         MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
-        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
        /* 4.2.2.2 Attempt to update */
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
-        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
-        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
-        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
-        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
-        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
        /* 4.2.2.3 Limited service */
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
-        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
-        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
        /* 4.2.2.4 No IMSI */
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_IMSI),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
        /* 4.2.2.5 PLMN search, normal service */
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
-        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
-        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
-        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
-        GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
         MMSS_EST_REQ, gsm48_mm_init_mm_no_rr},
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
         MMSMS_EST_REQ, gsm48_mm_init_mm_no_rr},
-       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
-        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
        /* 4.2.2.4 PLMN search */
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH),
         MMCC_EST_REQ, gsm48_mm_init_mm_no_rr},
@@ -991,6 +1061,89 @@ static struct eventstate {
         MMSS_EST_REQ, gsm48_mm_init_mm_other},
        {ALL_STATES, ALL_STATES,
         MMSMS_EST_REQ, gsm48_mm_init_mm_other},
+};
+
+#define DOWNSLLEN \
+       (sizeof(downstatelist) / sizeof(struct downstate))
+
+int gsm48_mmxx_downmsg(struct osmocom_ms *ms, struct msgb msg)
+{
+       struct gsm48_mmlayer *mm = &ms->mmlayer;
+       struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data;
+       int msg_type = mmh->msg_type;
+
+       DEBUGP(DMM, "(ms %s) Received '%s' event in state %s", ms->name,
+               get_mmevent_name(msg_type), gsm48_mm_state_names[mm->state]);
+       if (mm->state == GSM48_MM_ST_MM_ILDE)
+               DEBUGP(DMM, " substate %s", gsm48_mm_substate_names[mm->substate]);
+       DEBUGP(DMM, "\n");
+
+       /* Find function for current state and message */
+       for (i = 0; i < DOWNSLLEN; i++)
+               if ((msg_type == downstatelist[i].type)
+                && ((1 << mm->state) & downstatelist[i].states)
+                && ((1 << mm->substate) & downstatelist[i].substates))
+                       break;
+       if (i == DOWNSLLEN) {
+               DEBUGP(DMM, "Message unhandled at this state.\n");
+               return 0;
+       }
+
+       rc = downstatelist[i].rout(ms, msg);
+
+       return rc;
+}
+
+/* state trasitions for mobile management events */
+static struct eventstate {
+       u_int32_t       states;
+       u_int32_t       substates;
+       int             type;
+       int             (*rout) (struct osmocom_ms *ms, struct msgb *msg);
+} eventstatelist[] = {
+       /* 4.2.2.1 Normal service */
+** todo: check if there is a senders of every event
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE),
+        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
+       /* 4.2.2.2 Attempt to update */
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
+        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
+        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
+        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
+        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE),
+        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
+       /* 4.2.2.3 Limited service */
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
+        GSM48_MM_EVENT_NEW_LAI, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE),
+        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
+       /* 4.2.2.4 No IMSI */
+       /* 4.2.2.5 PLMN search, normal service */
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
+        GSM48_MM_EVENT_TIMEOUT_T3211, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
+        GSM48_MM_EVENT_TIMEOUT_T3213, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
+        GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_update_no_rr},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
+        GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start},
+       {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH_NORMAL),
+        GSM48_MM_EVENT_PAGING, gsm48_mm_paging},
+       /* 4.2.2.4 PLMN search */
        /* IMSI detach in other cases */
        {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_IMSI), /* no SIM */
         GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_end},
@@ -1050,16 +1203,15 @@ todo all other states (sim removed)
 #define EVENTSLLEN \
        (sizeof(eventstatelist) / sizeof(struct eventstate))
 
-/* MM event handler */
-int mm_event(struct osmocom_ms *ms, int msg_type, struct gsm48_mmevent *mmevent)
+int gsm48_mm_event(struct osmocom_ms *ms, int msg_type, struct gsm48_mmevent *mmevent)
 {
        struct gsm48_mmlayer *mm = &ms->mmlayer;
        int msg_type = mmevent->msg_type;
 
        DEBUGP(DMM, "(ms %s) Received '%s' event in state %s", ms->name,
-               get_mmevent_name(msg_type), mm_state_names[mm->state]);
+               get_mmevent_name(msg_type), gsm48_mm_state_names[mm->state]);
        if (mm->state == GSM48_MM_ST_MM_ILDE)
-               DEBUGP(DMM, " substate %s", mm_substate_names[mm->substate]);
+               DEBUGP(DMM, " substate %s", gsm48_mm_substate_names[mm->substate]);
        DEBUGP(DMM, "\n");
 
        /* Find function for current state and message */
@@ -1293,9 +1445,10 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
 {
        struct gsm48_hdr *gh = msgb_l3(msg);
        int msg_type = gh->msg_type & 0xbf;
+       struct gsm48_cc_hdr *mmh;
 
-       /* pull the MM header */
-       msgb_pull(msg, sizeof(struct gsm48_mm_hdr));
+       /* pull the RR header */
+       msgb_pull(msg, sizeof(struct gsm48_rr_hdr));
 
        /* forward message */
        switch (pdisc) {
@@ -1304,18 +1457,26 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
 
        case GSM48_PDISC_CC:
                /* push new header */
-               msgb_push(msg, sizeof(struct gsm48_cc_hdr));
-               cch = (struct gsm48_cc_hdr *)msg->data;
-               cch->msg_type = MM_DATA_IND;
+               msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+               mmh = (struct gsm48_mmxx_hdr *)msg->data;
+               mmh->msg_type = GSM48_MMCC_DATA_IND;
 
                return gsm48_cc_upmsg(ms, msg);
 
 #if 0
+       case GSM48_PDISC_SS:
+               /* push new header */
+               msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+               mmh = (struct gsm48_mmxx_hdr *)msg->data;
+               mmh->msg_type = GSM48_MMSS_DATA_IND;
+
+               return gsm48_sms_upmsg(ms, msg);
+
        case GSM48_PDISC_SMS:
                /* push new header */
-               msgb_push(msg, sizeof(struct gsm48_sms_hdr));
-               smsh = (struct gsm48_smscc_hdr *)msg->data;
-               smsh->msg_type = MM_DATA_IND;
+               msgb_push(msg, sizeof(struct gsm48_mmxx_hdr));
+               mmh = (struct gsm48_mmxx_hdr *)msg->data;
+               mmh->msg_type = GSM48_MMSMS_DATA_IND;
 
                return gsm48_sms_upmsg(ms, msg);
 #endif
@@ -1327,7 +1488,7 @@ static int gsm48_mm_data_ind(struct osmocom_ms *ms, struct msgb *msg)
        }
 
        DEBUGP(DMM, "(ms %s) Received '%s' in MM state %s\n", ms->name,
-               gsm48_mm_msg_name(msg_type), mm_state_names[mm->state]);
+               gsm48_mm_msg_name(msg_type), gsm48_mm_state_names[mm->state]);
 
        /* find function for current state and message */
        for (i = 0; i < MMDATASLLEN; i++)
@@ -1395,6 +1556,7 @@ static int gsm48_mm_est_loc_upd(struct osmocom_ms *ms, struct gsm_rr *est)
        /* MI */
        gsm48_encode_mi(nmsg, subscr, mi_type);
 
+       /* pussh RR header and send down */
        return gsm48_mm_to_rr(ms, nmsg, RR_DATA_REQ);
 }
 
@@ -1511,7 +1673,7 @@ static int gsm48_rcv_rr(struct osmocom_ms *ms, struct msgb *msg)
        int msg_type = msg->msg_type;
 
        DEBUGP(DMM, "(ms %s) Received '%s' from RR in state %s\n", ms->name,
-               gsm48_rr_msg_name(msg_type), mm_state_names[mm->state]);
+               gsm48_rr_msg_name(msg_type), gsm48_mm_state_names[mm->state]);
 
        /* find function for current state and message */
        for (i = 0; i < RRDATASLLEN; i++)
index 8640ffb..bb7b58f 100644 (file)
@@ -100,7 +100,7 @@ static const struct value_string gsm48_rr_msg_names[] = {
 
 const char *get_rr_name(int value)
 {
-       return get_value_string(rr_names, value);
+       return get_value_string(gsm48_rr_msg_names, value);
 }
 
 /* allocate GSM 04.08 layer 3 message */
@@ -222,7 +222,7 @@ static int gsm_rr_tx_rr_status(struct osmocom_ms *ms, uint8_t cause)
 {
        struct gsm_rrlayer *rr = &ms->rrlayer;
        struct msgb *nmsg;
-       struct gsm48_hdr *ngh;
+       struct gsm48_hdr *gh;
        struct gsm48_rr_status *st;
 
        nmsg = gsm48_l3_msgb_alloc();
@@ -250,7 +250,7 @@ static int gsm_rr_tx_cip_mode_cpl(struct osmocom_ms *ms, uint8_t cr)
        struct gsm_rrlayer *rr = &ms->rrlayer;
        struct gsm_subscriber *subcr = ms->subscr;
        struct msgb *nmsg;
-       struct gsm48_hdr *ngh;
+       struct gsm48_hdr *gh;
        u_int8_t buf[11], *ie;
 
        nmsg = gsm48_l3_msgb_alloc();
@@ -2306,9 +2306,9 @@ static int gsm_rr_data_ind(struct osmocom_ms *ms, struct msbg *msg)
        msgb_pull(msg, msgb_l3(msg) - msg->data);
 
        /* push RR header */
-       msgb_push(msg, sizeof(struct gsm48_mm_hdr));
-       mmh = (struct gsm48_mm_hdr *)msg->data;
-       mmh->msg_type = GSM48_RR_DATA_IND;
+       msgb_push(msg, sizeof(struct gsm48_rr_hdr));
+       rrh = (struct gsm48_rr_hdr *)msg->data;
+       rrh->msg_type = GSM48_RR_DATA_IND;
 
        return gsm48_mm_upmsg(ms, msg);
 }
index b374ae6..ff10687 100644 (file)
@@ -78,7 +78,7 @@ struct gsm_support {
        uint8_t gps_conv;
 
        /* IMEI */
-       char imei[16];
+       char imei[15];
        char imeidv[17];
 };