lists.osmocom.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
June
May
April
March
February
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
List overview
Download
gerrit-log
September 2023
----- 2025 -----
June 2025
May 2025
April 2025
March 2025
February 2025
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
gerrit-log@lists.osmocom.org
1 participants
1947 discussions
Start a n
N
ew thread
[S] Change in osmocom-bb[master]: ASCI: Add channel description to messages from MM to RR layer
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34490?usp=email
) Change subject: ASCI: Add channel description to messages from MM to RR layer ...................................................................... ASCI: Add channel description to messages from MM to RR layer This is required to specify channel when activating the group channel. In this implementation GCC/BCC layer maintains the channel. Related: OS#5364 Change-Id: I154f1f0e49ffa508d01a026da8e73faa7fdbab40 --- M src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h M src/host/layer23/src/mobile/gsm48_mm.c 2 files changed, 27 insertions(+), 11 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/90/34490/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h index fb07cc9..9b73ab2 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h @@ -62,6 +62,7 @@ uint32_t msg_type; /* RR-* primitive */ uint8_t sapi; uint8_t cause; + struct gsm48_chan_desc ch_desc; } __attribute__((packed)); /* GSM 04.07 9.1.1 */ diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c index 20bbae2..dc6e079 100644 --- a/src/host/layer23/src/mobile/gsm48_mm.c +++ b/src/host/layer23/src/mobile/gsm48_mm.c @@ -868,7 +868,7 @@ /* push RR header and send to RR */ static int gsm48_mm_to_rr(struct osmocom_ms *ms, struct msgb *msg, int msg_type, - uint8_t sapi, uint8_t cause) + uint8_t sapi, uint8_t cause, struct gsm48_chan_desc *ch_desc) { struct gsm48_rr_hdr *rrh; @@ -878,6 +878,8 @@ rrh->msg_type = msg_type; rrh->sapi = sapi; rrh->cause = cause; + if (ch_desc) + memcpy(&rrh->ch_desc, ch_desc, sizeof(rrh->ch_desc)); /* send message to RR */ return gsm48_rr_downmsg(ms, msg); @@ -1610,7 +1612,7 @@ *reject_cause = cause; /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0, NULL); } /* 4.3.1.2 sending TMSI REALLOCATION COMPLETE message */ @@ -1630,7 +1632,7 @@ ngh->msg_type = GSM48_MT_MM_TMSI_REALL_COMPL; /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0, NULL); } /* 4.3.1 TMSI REALLOCATION COMMAND is received */ @@ -1746,7 +1748,7 @@ memcpy(sres, mme->sres, 4); /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0, NULL); } /* 4.3.2.5 AUTHENTICATION REJECT is received */ @@ -1850,7 +1852,7 @@ gsm48_encode_mi(ms, nmsg, false, mi_type, false); /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0, NULL); } /* 4.3.4.1 sending IMSI DETACH INDICATION message */ @@ -1897,7 +1899,7 @@ /* push RR header and send down */ mm->est_cause = RR_EST_CAUSE_OTHER_SDCCH; - return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause); + return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause, NULL); } /* detach has ended */ @@ -2429,7 +2431,7 @@ /* push RR header and send down */ mm->est_cause = RR_EST_CAUSE_LOC_UPD; - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, 0, mm->est_cause); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, 0, mm->est_cause, NULL); } /* 4.4.4.1 RR is esablised during location update */ @@ -2885,7 +2887,7 @@ /* prio is optional for eMLPP */ /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause); + return gsm48_mm_to_rr(ms, nmsg, rr_prim, 0, mm->est_cause, NULL); } /* cm service abort message from upper layer @@ -2907,7 +2909,7 @@ ngh->msg_type = GSM48_MT_MM_CM_SERV_ABORT; /* push RR header and send down */ - return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0, NULL); } /* cm service acknowledge is received from lower layer */ @@ -3312,7 +3314,7 @@ if (!nmsg) return -ENOMEM; return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_EST_REQ, - conn_found->sapi, 0); + conn_found->sapi, 0, NULL); } nmsg = gsm48_mmxx_msgb_alloc(GSM48_MMSMS_EST_CNF, conn_found->ref, conn_found->transaction_id, @@ -3481,7 +3483,7 @@ msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr)); /* push RR header and send down */ - return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, conn->sapi, 0); + return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, conn->sapi, 0, NULL); } /* release of MM connection (active state) */ -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34490?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I154f1f0e49ffa508d01a026da8e73faa7fdbab40 Gerrit-Change-Number: 34490 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[L] Change in osmocom-bb[master]: ASCI: Add group receive and transmit mode support to MM layer
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34492?usp=email
) Change subject: ASCI: Add group receive and transmit mode support to MM layer ...................................................................... ASCI: Add group receive and transmit mode support to MM layer Related: OS#5364 Change-Id: I05957182a57423ad947ab200b52f65fde859e110 --- M src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h M src/host/layer23/src/mobile/gsm48_mm.c 2 files changed, 700 insertions(+), 110 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/92/34492/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h index 4f47c9b..d0de235 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h @@ -8,8 +8,8 @@ #define GSM48_MMCC_CLASS 0x100 #define GSM48_MMSS_CLASS 0x200 #define GSM48_MMSMS_CLASS 0x300 -#define GSM48_MMBCC_CLASS 0x500 -#define GSM48_MMGCC_CLASS 0x600 +#define GSM48_MMGCC_CLASS 0x500 +#define GSM48_MMBCC_CLASS 0x600 #define GSM48_MMXX_REL_IND 0x022 #define GSM48_MMCC_EST_REQ 0x110 #define GSM48_MMCC_EST_IND 0x112 @@ -66,6 +66,13 @@ #define GSM48_MMGCC_REEST_REQ 0x560 #define GSM48_MMGCC_REEST_CNF 0x561 #define GSM48_MMGCC_ERR_IND 0x572 +#define GSM48_MMGCC_NOTIF_IND 0x582 +#define GSM48_MMGCC_GROUP_REQ 0x590 +#define GSM48_MMGCC_GROUP_CNF 0x591 +#define GSM48_MMGCC_UPLINK_REQ 0x5a0 +#define GSM48_MMGCC_UPLINK_CNF 0x5a1 +#define GSM48_MMGCC_UPLINK_REL_REQ 0x5a8 +#define GSM48_MMGCC_UPLINK_REL_IND 0x5aa #define GSM48_MMBCC_EST_REQ 0x610 #define GSM48_MMBCC_EST_CNF 0x611 #define GSM48_MMBCC_REL_REQ 0x620 @@ -77,18 +84,32 @@ #define GSM48_MMBCC_REEST_REQ 0x660 #define GSM48_MMBCC_REEST_CNF 0x661 #define GSM48_MMBCC_ERR_IND 0x672 +#define GSM48_MMBCC_NOTIF_IND 0x682 +#define GSM48_MMBCC_GROUP_REQ 0x690 +#define GSM48_MMBCC_GROUP_CNF 0x691 +#define GSM48_MMBCC_UPLINK_REQ 0x6a0 +#define GSM48_MMBCC_UPLINK_CNF 0x6a1 +#define GSM48_MMBCC_UPLINK_REL_REQ 0x6a8 +#define GSM48_MMBCC_UPLINK_REL_IND 0x6aa + #define MMXX_ALLOC_SIZE 256 #define MMXX_ALLOC_HEADROOM 64 +#define MMXX_NOTIFY_SETUP 0 +#define MMXX_NOTIFY_RELEASE 1 + /* MMxx-SAP header */ struct gsm48_mmxx_hdr { - uint16_t msg_type; /* MMxx_* primitive */ - uint32_t ref; /* reference to transaction */ - uint32_t transaction_id; /* transaction identifier */ - uint8_t sapi; /* sapi */ - uint8_t emergency; /* emergency type of call */ - uint8_t cause; /* cause used for release */ + uint16_t msg_type; /* MMxx_* primitive */ + uint32_t ref; /* reference to transaction */ + uint32_t transaction_id; /* transaction identifier */ + uint8_t sapi; /* sapi */ + uint8_t emergency; /* emergency type of call */ + uint8_t cause; /* cause used for release */ + uint8_t notify; /* notify ongoing ASCI call */ + bool ch_desc_present; /* notifies channel */ + struct gsm48_chan_desc ch_desc; /* group channel */ } __attribute__((packed)); /* GSM 6.1.2 */ @@ -233,6 +254,12 @@ /* sapi 3 */ int sapi3_link; + + /* VGCS additional states */ + bool vgcs; /* We are in group/broadcast mode. */ + bool vgcs_group_call; /* This is a group call. */ + uint32_t vgcs_callref; /* Callref of this call. */ + bool vgcs_normal_service; /* Service state before group transmit mode. */ }; /* MM connection entry */ diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c index dc6e079..7b7cb59 100644 --- a/src/host/layer23/src/mobile/gsm48_mm.c +++ b/src/host/layer23/src/mobile/gsm48_mm.c @@ -144,6 +144,9 @@ * During LIMITED SERVICE state: (4.2.2.3) * - reject MM connection except for emergency calls * - perform location update, if new LAI is entered + * - indicate GCC/BCC calls with channel description only + * - reject joining to GCC/BCC calls without channel description + * - accept joining to GCC/BCC calls with channel description * * * The LOCATION UPDATE NEEDED state is entered if: @@ -176,6 +179,9 @@ * - accept MM connection for emergency calls * - trigger location update on any other MM connection * - respond to paging (with IMSI only, because in U2 TMSI is not valid) + * - indicate GCC/BCC calls with channel description only + * - reject joining to GCC/BCC calls without channel description + * - accept joining to GCC/BCC calls with channel description * * * The NORMAL SERVICE state is entered if: @@ -185,12 +191,52 @@ * - and SIM LAI == cell * * During NORMAL SERVICE state: (4.2.2.1) - * - on expirery of T3211 or T3213: Perform location updated - * - on expirery of T3212: Perform location updated + * - on expirery of T3211 or T3213: Perform location update + * - on expirery of T3212: Perform location update * - on change of LAI: Perform location update * - perform IMSI detach * - perform MM connections * - respond to paging + * - indicate GCC/BCC calls with and without channel description + * - accept joining to GCC/BCC calls without channel description + * -> The GCC/BCC layer waits for channel description before joining. + * - accept joining to GCC/BCC calls with channel description + * + * + * The RECEIVING GROUP CALL (NORMAL SERVICE) is entered if: + * - the upper layer requests to join to GCC/BCC call + * - and service state is NORMAL SERVICE + * + * During RECEIVING GROUP CALL (NORMAL SERVICE) state: (4.2.2.7) + * - reject all MM connections + * - indicate notifications and paging to GCC or BCC layer + * -> If supported by RR layer. + * The following events are not be supported here: + * - perform IMSI detach (This is delayed until the call has ended.) + * - on expirery of T3211 or T3213: Perform location update + * - on expirery of T3212: Perform location update + * - accept MM connections + * - on change of LAI: Perform location update + * - accept joining to GCC/BCC calls without channel description + * - accept joining to GCC/BCC calls with channel description + * + * + * The RECEIVING GROUP CALL (LIMITED SERVICE) is entered if: + * - the upper layer requests to join to GCC/BCC call + * - and service state is LIMITED SERVICE or ATTEMPTING TO UPDATE + * + * During RECEIVING GROUP CALL (LIMITED SERVICE) state: (4.2.2.8) + * - reject all MM connections + * - indicate notifications and paging to GCC or BCC layer + * -> If supported by RR layer. + * The following events are not be supported here: + * - reject MM connection except for emergency calls + * - on expirery of T3212: Perform location updated + * - reject joining to GCC/BCC calls without channel description + * - accept joining to GCC/BCC calls with channel description + * + * + * A group call is only accepted, if there is no other MM connection ongoing. * * * gsm48_mm_set_plmn_search() is used enter PLMN SEARCH or PLMN SEARCH NORMAL @@ -223,6 +269,33 @@ * * gsm48_mm_cell_selected() is used to select the Service state. * + * + * New primitives are invented for group/broadcast calls. They are not + * specified in any recommendation. They are: + * + * - MMxCC_NOTIF_IND: The MM layer indicates new/updated/ceased calls. This is + * completely independant from the state of the MM layer. + * - MMxCC_GROUP_REQ: The GCC/BCC layer requests group channel in receive mode. + * This mode has no MM connection. Speical flags (mm->vgcs*) are used to + * define that mode and store the reference (callref + group|broadcast). This + * reference is used for messages towards GCC/BCC layer. The state is IDLE + * and the sub-state defines group receive mode at normal service or at + * limited service state. + * - MMxCC_GROUP_CNF: The MM layer confirms group channel. + * - MMxCC_UPLINK_REQ: The GCC/BCC layer requests uplink (group transmit mode). + * The MM layer changes to group transmit mode. + * - MMxCC_UPLINK_CNF: The MM layer confirms uplink. (Uplink was granted.) + * - MMxCC_UPLINK_REL_REQ: The GCC/BCC layer requests release of uplink. + * - MMxCC_UPLINK_REL_IND: The MM layer indicates/confirms release of uplink + * + * Existing primitives are used with group calls: + * + * MMxCC_REL_IND: Failed to establish group receive mode. + * MMxCC_ERR_IND: Abort received from RR layer in group receive or transmit mode. + * MMxCC_REL_REQ: Leave group call (receive mode or transmit mode). + * + * The group call is released at MM layer, if one of the primitives above are + * received or transmitted. */ /* @@ -574,6 +647,8 @@ { GSM48_MM_EVENT_USER_PLMN_SEL, "MM_EVENT_USER_PLMN_SEL" }, { GSM48_MM_EVENT_LOST_COVERAGE, "MM_EVENT_LOST_COVERAGE" }, { GSM48_MM_EVENT_NOTIFICATION, "MM_EVENT_NOTIFICATION" }, + { GSM48_MM_EVENT_UPLINK_FREE, "MM_EVENT_UPLINK_FREE" }, + { GSM48_MM_EVENT_UPLINK_BUSY, "MM_EVENT_UPLINK_BUSY" }, { 0, NULL } }; @@ -658,6 +733,26 @@ { GSM48_MMSMS_ERR_IND, "MMSMS_ERR_IND" }, { GSM48_MMSMS_PROMPT_IND, "MMSMS_PROMPT_IND" }, { GSM48_MMSMS_PROMPT_REJ, "MMSMS_PROMPT_REJ" }, + { GSM48_MMGCC_EST_REQ, "MMGCC_EST_REQ" }, + { GSM48_MMGCC_EST_CNF, "MMGCC_EST_CNF" }, + { GSM48_MMGCC_REL_REQ, "MMGCC_REL_REQ" }, + { GSM48_MMGCC_REL_IND, "MMGCC_REL_IND" }, + { GSM48_MMGCC_DATA_REQ, "MMGCC_DATA_REQ" }, + { GSM48_MMGCC_DATA_IND, "MMGCC_DATA_IND" }, + { GSM48_MMGCC_UNIT_DATA_REQ, "MMGCC_UNIT_DATA_REQ" }, + { GSM48_MMGCC_UNIT_DATA_IND, "MMGCC_UNIT_DATA_IND" }, + { GSM48_MMGCC_REEST_REQ, "MMBCC_REEST_REQ" }, + { GSM48_MMGCC_REEST_CNF, "MMBCC_REEST_CNF" }, + { GSM48_MMGCC_ERR_IND, "MMGCC_ERR_IND" }, + { GSM48_MMGCC_NOTIF_IND, "MMGCC_NOTIF_IND" }, + { GSM48_MMGCC_GROUP_REQ, "MMGCC_GROUP_REQ" }, + { GSM48_MMGCC_GROUP_CNF, "MMGCC_GROUP_CNF" }, + { GSM48_MMGCC_UPLINK_REQ, "MMGCC_UPLINK_REQ" }, + { GSM48_MMGCC_UPLINK_CNF, "MMGCC_UPLINK_CNF" }, + { GSM48_MMGCC_UPLINK_REL_REQ, "MMGCC_UPLINK_REL_REQ" }, + { GSM48_MMGCC_UPLINK_REL_IND, "MMGCC_UPLINK_REL_CNF" }, + { GSM48_MMGCC_UPLINK_FREE_IND, "MMGCC_UPLINK_FREE_IND" }, + { GSM48_MMGCC_UPLINK_BUSY_IND, "MMGCC_UPLINK_BUSY_IND" }, { GSM48_MMBCC_EST_REQ, "MMBCC_EST_REQ" }, { GSM48_MMBCC_EST_CNF, "MMBCC_EST_CNF" }, { GSM48_MMBCC_REL_REQ, "MMBCC_REL_REQ" }, @@ -669,17 +764,15 @@ { GSM48_MMBCC_REEST_REQ, "MMBCC_REEST_REQ" }, { GSM48_MMBCC_REEST_CNF, "MMBCC_REEST_CNF" }, { GSM48_MMBCC_ERR_IND, "MMBCC_ERR_IND" }, - { GSM48_MMGCC_EST_REQ, "MMGCC_EST_REQ" }, - { GSM48_MMGCC_EST_CNF, "MMGCC_EST_CNF" }, - { GSM48_MMGCC_REL_REQ, "MMGCC_REL_REQ" }, - { GSM48_MMGCC_REL_IND, "MMGCC_REL_IND" }, - { GSM48_MMGCC_DATA_REQ, "MMGCC_DATA_REQ" }, - { GSM48_MMGCC_DATA_IND, "MMGCC_DATA_IND" }, - { GSM48_MMGCC_UNIT_DATA_REQ, "MMGCC_UNIT_DATA_REQ" }, - { GSM48_MMGCC_UNIT_DATA_IND, "MMGCC_UNIT_DATA_IND" }, - { GSM48_MMGCC_REEST_REQ, "MMGCC_REEST_REQ" }, - { GSM48_MMGCC_REEST_CNF, "MMGCC_REEST_CNF" }, - { GSM48_MMGCC_ERR_IND, "MMGCC_ERR_IND" }, + { GSM48_MMBCC_NOTIF_IND, "MMBCC_NOTIF_IND" }, + { GSM48_MMBCC_GROUP_REQ, "MMBCC_GROUP_REQ" }, + { GSM48_MMBCC_GROUP_CNF, "MMBCC_GROUP_CNF" }, + { GSM48_MMBCC_UPLINK_REQ, "MMBCC_UPLINK_REQ" }, + { GSM48_MMBCC_UPLINK_CNF, "MMBCC_UPLINK_CNF" }, + { GSM48_MMBCC_UPLINK_REL_REQ, "MMBCC_UPLINK_REL_REQ" }, + { GSM48_MMBCC_UPLINK_REL_IND, "MMBCC_UPLINK_REL_CNF" }, + { GSM48_MMBCC_UPLINK_FREE_IND, "MMBCC_UPLINK_FREE_IND" }, + { GSM48_MMBCC_UPLINK_BUSY_IND, "MMBCC_UPLINK_BUSY_IND" }, { 0, NULL } }; @@ -911,8 +1004,8 @@ "wait for RR connection active", "MM idle", "wait for additional outgoing MM connection", - "MM_CONN_ACTIVE_VGCS", - "WAIT_RR_CONN_VGCS", + "MM connection active (group transmit mode)", + "wait for RR connection (group transmit mode)", "location updating pending", "IMSI detach pending", "RR connection release not allowed" @@ -928,8 +1021,8 @@ "location updating needed", "PLMN search", "PLMN search (normal)", - "RX_VGCS_NORMAL", - "RX_VGCS_LIMITED" + "receiving group call (normal service)", + "receiving group call (limiteed service)" }; /* change state from LOCATION UPDATE NEEDED to ATTEMPTING TO UPDATE */ @@ -1001,6 +1094,11 @@ l23_vty_ms_notify(ms, "Trying to register with network %s, %s...\n", gsm_get_mcc(plmn->plmn.mcc), gsm_get_mnc(&plmn->plmn)); break; + case GSM48_MM_SST_RX_VGCS_NORMAL: + case GSM48_MM_SST_RX_VGCS_LIMITED: + l23_vty_ms_notify(ms, NULL); + l23_vty_ms_notify(ms, "Listening to %s call.\n", (mm->vgcs_group_call) ? "group" : "broadcast"); + break; } } @@ -1124,6 +1222,7 @@ struct gsm48_mmlayer *mm = &ms->mmlayer; struct gsm322_cellsel *cs = &ms->cellsel; struct gsm48_sysinfo *s = &cs->sel_si; + bool vgcs = mm->vgcs; if (cs->state != GSM322_C3_CAMPED_NORMALLY && cs->state != GSM322_C7_CAMPED_ANY_CELL) { @@ -1174,7 +1273,8 @@ GSM48_MM_SST_ATTEMPT_UPDATE); else new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_NORMAL_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_NORMAL + : GSM48_MM_SST_NORMAL_SERVICE); return 0; } @@ -1186,13 +1286,15 @@ /* location update not allowed */ LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed PLMN.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); } else if (gsm322_is_forbidden_la(ms, &cs->sel_cgi.lai)) { /* location update not allowed */ LOGP(DMM, LOGL_INFO, "Loc. upd. not allowed LA.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); } else /* 4.4.4.9 if cell is barred, don't start */ if ((!subscr->acc_barr && s->cell_barr) @@ -1200,19 +1302,22 @@ (s->class_barr ^ 0xffff)))) { LOGP(DMM, LOGL_INFO, "Loc. upd. no access.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); } else { /* location update allowed */ LOGP(DMM, LOGL_INFO, "Loc. upd. allowed.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LOC_UPD_NEEDED); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); } } else { /* location update not allowed */ LOGP(DMM, LOGL_INFO, "We are camping on any cell as returning " "to MM IDLE\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); } return 0; @@ -1239,6 +1344,7 @@ struct gsm322_cellsel *cs = &ms->cellsel; struct gsm48_sysinfo *s = &cs->sel_si; struct gsm_settings *set = &ms->settings; + bool vgcs = mm->vgcs; /* no SIM is inserted */ if (!subscr->sim_valid) { @@ -1258,7 +1364,8 @@ LOGP(DMM, LOGL_INFO, "Valid in location area.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_NORMAL_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_NORMAL + : GSM48_MM_SST_NORMAL_SERVICE); /* send message to PLMN search process */ nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS); @@ -1273,7 +1380,8 @@ LOGP(DMM, LOGL_INFO, "Attachment not required.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_NORMAL_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_NORMAL + : GSM48_MM_SST_NORMAL_SERVICE); /* send message to PLMN search process */ nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_SUCCESS); @@ -1295,7 +1403,8 @@ LOGP(DMM, LOGL_INFO, "Selected cell is forbidden.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); /* send message to PLMN search process */ nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED); @@ -1316,7 +1425,8 @@ LOGP(DMM, LOGL_INFO, "Selected cell not found.\n"); new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_LIMITED_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_LIMITED + : GSM48_MM_SST_LIMITED_SERVICE); /* send message to PLMN search process */ nmsg = gsm322_msgb_alloc(GSM322_EVENT_REG_FAILED); @@ -1424,9 +1534,8 @@ /* new MM connection state */ static void new_conn_state(struct gsm48_mm_conn *conn, int state) { - LOGP(DMM, LOGL_INFO, "(ref 0x%x proto %d) new state %s -> %s\n", conn->ref, conn->protocol - gsm48_mmxx_state_names[conn->state], - gsm48_mmxx_state_names[state]); + LOGP(DMM, LOGL_INFO, "(ref 0x%x proto %d) new state %s -> %s\n", conn->ref, conn->protocol, + gsm48_mmxx_state_names[conn->state], gsm48_mmxx_state_names[state]); conn->state = state; } @@ -2144,6 +2253,8 @@ if (mm->state == GSM48_MM_ST_MM_IDLE && (mm->substate == GSM48_MM_SST_NO_CELL_AVAIL || mm->substate == GSM48_MM_SST_LIMITED_SERVICE + || mm->substate == GSM48_MM_SST_RX_VGCS_NORMAL + || mm->substate == GSM48_MM_SST_RX_VGCS_LIMITED || mm->substate == GSM48_MM_SST_PLMN_SEARCH || mm->substate == GSM48_MM_SST_PLMN_SEARCH_NORMAL)) return 0; @@ -2275,6 +2386,7 @@ struct gsm_subscriber *subscr = &ms->subscr; struct gsm322_cellsel *cs = &ms->cellsel; struct gsm48_sysinfo *s = &cs->sel_si; + bool vgcs = mm->vgcs; struct msgb *nmsg; /* in case we already have a location update going on */ @@ -2314,7 +2426,8 @@ /* go straight to normal service state */ new_mm_state(mm, GSM48_MM_ST_MM_IDLE, - GSM48_MM_SST_NORMAL_SERVICE); + (vgcs) ? GSM48_MM_SST_RX_VGCS_NORMAL + : GSM48_MM_SST_NORMAL_SERVICE); #if 0 /* don't send message, if we got not triggered by PLMN search */ @@ -3396,6 +3509,7 @@ { struct gsm48_mmlayer *mm = &ms->mmlayer; struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data; + uint32_t msg_type = rrh->msg_type; int cause; /* stop RR release timer */ @@ -3415,11 +3529,13 @@ cause = 47; } + LOGP(DMM, LOGL_INFO, "Aborting connection with cause %d\n", cause); + /* stop MM connection timer */ stop_mm_t3230(mm); /* release all connections */ - gsm48_mm_release_mm_conn(ms, 1, cause, 1, 0); + gsm48_mm_release_mm_conn(ms, 1, cause, (msg_type == GSM48_RR_ABORT_IND), 0); /* return to MM IDLE */ return gsm48_mm_return_idle(ms, NULL); @@ -3463,27 +3579,32 @@ struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data; struct gsm48_mm_conn *conn; int msg_type = mmh->msg_type; + uint8_t sapi; - /* get connection, if not exist (anymore), release */ - conn = mm_conn_by_ref_and_class(mm, mmh->ref, (mmh->msg_type & GSM48_MMXX_MASK)); - if (!conn) { - LOGP(DMM, LOGL_INFO, "MMXX_DATA_REQ with unknown (already " - "released) ref=%x, sending MMXX_REL_IND\n", mmh->ref); - mmh->msg_type = GSM48_MMXX_REL_IND | (msg_type & GSM48_MMXX_MASK); - mmh->cause = 31; + if (mm->state == GSM48_MM_ST_MM_CONN_ACTIVE_VGCS) { + /* Group transmit mode has no MM connection. */ + sapi = 0; + } else { + /* get connection, if not exist (anymore), release */ + conn = mm_conn_by_ref_and_class(mm, mmh->ref, (mmh->msg_type & GSM48_MMXX_MASK)); + if (!conn) { + LOGP(DMM, LOGL_INFO, "MMXX_DATA_REQ with unknown (already " + "released) ref=%x, sending MMXX_REL_IND\n", mmh->ref); + mmh->msg_type = GSM48_MMXX_REL_IND | (msg_type & GSM48_MMXX_MASK); + mmh->cause = 31; - /* mirror message with REL_IND + cause */ - return gsm48_mmxx_upmsg(ms, msg); + /* mirror message with REL_IND + cause */ + return gsm48_mmxx_upmsg(ms, msg); + } + /* set SAPI, if upper layer does not do it correctly */ + sapi = conn->sapi; } - /* set SAPI, if upper layer does not do it correctly */ - mmh->sapi = conn->sapi; - /* pull MM header */ msgb_pull(msg, sizeof(struct gsm48_mmxx_hdr)); /* push RR header and send down */ - return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, conn->sapi, 0, NULL); + return gsm48_mm_to_rr(ms, msg, GSM48_RR_DATA_REQ, sapi, 0, NULL); } /* release of MM connection (active state) */ @@ -3590,6 +3711,333 @@ return gsm48_mm_return_idle(ms, NULL); } +/* The RR indicates notification of ongoing VGCS/VBS calls. */ +static int gsm48_mm_notification(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mm_event *mme = (struct gsm48_mm_event *)msg->data; + uint32_t ref = osmo_load32be(mme->notification.gcr) >> 5; + uint16_t msg_type = (mme->notification.gcr[3] & 0x10) ? GSM48_MMGCC_NOTIF_IND : GSM48_MMBCC_NOTIF_IND; + struct gsm48_mmxx_hdr *mmh; + struct msgb *nmsg; + + /* Notification message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, ref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + mmh = (struct gsm48_mmxx_hdr *)nmsg->data; + mmh->notify = (mme->notification.gone) ? MMXX_NOTIFY_RELEASE : MMXX_NOTIFY_SETUP; + mmh->ch_desc_present = mme->notification.ch_desc_present; + memcpy(&mmh->ch_desc, &mme->notification.ch_desc, sizeof(mmh->ch_desc)); + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* The RR indicates uplink busy. */ +static int gsm48_mm_uplink_free(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct gsm48_mm_event *mme = (struct gsm48_mm_event *)msg->data; + struct msgb *nmsg; + uint16_t msg_type; + + if (mm->vgcs_group_call) + msg_type = (mme->msg_type == GSM48_MM_EVENT_UPLINK_BUSY) ? GSM48_MMGCC_UPLINK_BUSY_IND + : GSM48_MMGCC_UPLINK_FREE_IND; + else + msg_type = (mme->msg_type == GSM48_MM_EVENT_UPLINK_BUSY) ? GSM48_MMBCC_UPLINK_BUSY_IND + : GSM48_MMBCC_UPLINK_FREE_IND; + + LOGP(DMM, LOGL_INFO, "Update uplink free/busy state in group receive mode.\n"); + + /* Notification message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mm->vgcs_callref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* Join VGCS/VBS call as listener. */ +static int gsm48_mm_group_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data; + struct msgb *nmsg; + + LOGP(DMM, LOGL_INFO, "Request for joining a group call, trying to establish group receive mode.\n"); + + /* Store infos about group/broadcast call. */ + mm->vgcs = true; + mm->vgcs_group_call = (mmh->msg_type == GSM48_MMGCC_GROUP_REQ); + mm->vgcs_callref = mmh->ref; + mm->vgcs_normal_service = (mm->substate == GSM48_MM_SST_NORMAL_SERVICE); + + /* Change to VGCS substate. */ + new_mm_state(mm, GSM48_MM_ST_MM_IDLE, (mm->substate == GSM48_MM_SST_NORMAL_SERVICE) + ? GSM48_MM_SST_RX_VGCS_NORMAL : GSM48_MM_SST_RX_VGCS_LIMITED); + + /* Group recevie mode request to RR layer */ + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + + /* Push RR header and send to RR layer. */ + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_GROUP_REQ, 0, 0, &mmh->ch_desc); +} + +/* Joining VGCS/VBS call is not allowed in other states. */ +static int gsm48_mm_group_reject(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data; + uint16_t msg_type; + struct msgb *nmsg; + struct gsm48_mmxx_hdr *nmmh; + + LOGP(DMM, LOGL_NOTICE, "Joining group call rejected in current state.\n"); + + msg_type = (mmh->msg_type == GSM48_MMGCC_GROUP_REQ) ? GSM48_MMGCC_REL_IND : GSM48_MMBCC_REL_IND; + + /* Release message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mmh->ref, mmh->transaction_id, mmh->sapi); + if (!nmsg) + return -ENOMEM; + nmmh = (struct gsm48_mmxx_hdr *)nmsg->data; + nmmh->cause = GSM48_CC_CAUSE_CALL_REJECTED; + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* RR layer confirms group call. */ +static int gsm48_mm_group_cnf(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + uint16_t msg_type; + struct msgb *nmsg; + + LOGP(DMM, LOGL_NOTICE, "RR confirms group call.\n"); + + msg_type = (mm->vgcs_group_call) ? GSM48_MMGCC_GROUP_CNF: GSM48_MMBCC_GROUP_CNF; + + /* Uplink confirm message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mm->vgcs_callref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* RR layer releases group call channel. */ +static int gsm48_mm_group_rel_ind(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data; + uint16_t msg_type; + struct msgb *nmsg; + struct gsm48_mmxx_hdr *nmmh; + + LOGP(DMM, LOGL_NOTICE, "RR released or rejected group call channel.\n"); + + /* Disable group mode. */ + mm->vgcs = false; + + /* Change mode back to normal or limited service. */ + if (mm->substate == GSM48_MM_SST_RX_VGCS_LIMITED) + mm->substate = GSM48_MM_SST_LIMITED_SERVICE; + if (mm->substate == GSM48_MM_SST_RX_VGCS_NORMAL) + mm->substate = GSM48_MM_SST_NORMAL_SERVICE; + + /* Return IDLE, if not already. Also select the sub-state to use. */ + gsm48_mm_return_idle(ms, NULL); + + /* Release message to GCC/BCC layer */ + msg_type = (mm->vgcs_group_call) ? GSM48_MMGCC_REL_IND : GSM48_MMBCC_REL_IND; + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mm->vgcs_callref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + nmmh = (struct gsm48_mmxx_hdr *)nmsg->data; + switch (rrh->cause) { + case RR_REL_CAUSE_TRY_LATER: + /* Joining not yet possible */ + nmmh->cause = GSM48_CC_CAUSE_TEMP_FAILURE; + break; + case RR_REL_CAUSE_LOST_SIGNAL: + /* Lower layer failed. */ + nmmh->cause = GSM48_CC_CAUSE_TEMP_FAILURE; + break; + case RR_REL_CAUSE_NORMAL: + /* Channel was released by network. */ + nmmh->cause = GSM48_CC_CAUSE_NORM_CALL_CLEAR; + break; + default: + nmmh->cause = GSM48_CC_CAUSE_NORMAL_UNSPEC; + break; + } + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* Upper layer releases group call. */ +static int gsm48_mm_group_rel_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct msgb *nmsg; + + LOGP(DMM, LOGL_INFO, "Request to release group call in receive or transmit mode.\n"); + + /* Disable group mode. */ + mm->vgcs = false; + + /* Change mode back to normal or limited service. */ + if (mm->substate == GSM48_MM_SST_RX_VGCS_LIMITED) + mm->substate = GSM48_MM_SST_LIMITED_SERVICE; + if (mm->substate == GSM48_MM_SST_RX_VGCS_NORMAL) + mm->substate = GSM48_MM_SST_NORMAL_SERVICE; + + /* We are already IDLE. Also select the sub-state to use. */ + gsm48_mm_return_idle(ms, NULL); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + + /* Push RR header and send to RR layer. */ + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_GROUP_REL_REQ, 0, 0, NULL); +} + +/* Upper layer requests uplink. */ +static int gsm48_mm_uplink_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct msgb *nmsg; + + LOGP(DMM, LOGL_INFO, "Request for uplink, trying to establish group transmit mode.\n"); + + /* Go into uplink pending state. */ + new_mm_state(mm, GSM48_MM_ST_WAIT_RR_CONN_VGCS, 0); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + + /* Push RR header and send to RR layer. */ + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_UPLINK_REQ, 0, 0, NULL); +} + +/* Uplink not allowed in this state. */ +static int gsm48_mm_uplink_reject(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmxx_hdr *mmh = (struct gsm48_mmxx_hdr *)msg->data; + uint16_t msg_type; + struct msgb *nmsg; + struct gsm48_mmxx_hdr *nmmh; + + LOGP(DMM, LOGL_NOTICE, "Request for uplink rejected in current state.\n"); + + msg_type = (mmh->msg_type == GSM48_MMGCC_UPLINK_REQ) ? GSM48_MMGCC_UPLINK_REL_IND : GSM48_MMBCC_UPLINK_REL_IND; + + /* Uplink release message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mmh->ref, mmh->transaction_id, mmh->sapi); + if (!nmsg) + return -ENOMEM; + nmmh = (struct gsm48_mmxx_hdr *)nmsg->data; + nmmh->cause = GSM48_CC_CAUSE_CALL_REJECTED; + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* RR layer confirms uplink. */ +static int gsm48_mm_uplink_cnf(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + uint16_t msg_type; + struct msgb *nmsg; + + LOGP(DMM, LOGL_NOTICE, "RR confirms uplink.\n"); + + /* Go into group transmit state. */ + new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE_VGCS, 0); + + msg_type = (mm->vgcs_group_call) ? GSM48_MMGCC_UPLINK_CNF: GSM48_MMBCC_UPLINK_CNF; + + /* Uplink confirm message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mm->vgcs_callref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* RR layer releases/rejects uplink. */ +static int gsm48_mm_uplink_rel_ind(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_mmlayer *mm = &ms->mmlayer; + struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *)msg->data; + uint16_t msg_type; + struct msgb *nmsg; + struct gsm48_mmxx_hdr *nmmh; + + LOGP(DMM, LOGL_NOTICE, "RR released or rejected uplink.\n"); + + /* Change to VGCS substate. */ + new_mm_state(mm, GSM48_MM_ST_MM_IDLE, (mm->vgcs_normal_service) ? GSM48_MM_SST_RX_VGCS_NORMAL + : GSM48_MM_SST_RX_VGCS_LIMITED); + + msg_type = (mm->vgcs_group_call) ? GSM48_MMGCC_UPLINK_REL_IND: GSM48_MMBCC_UPLINK_REL_IND; + + /* Uplink reject message to GCC/BCC layer */ + nmsg = gsm48_mmxx_msgb_alloc(msg_type, mm->vgcs_callref, 0xff, 0); + if (!nmsg) + return -ENOMEM; + nmmh = (struct gsm48_mmxx_hdr *)nmsg->data; + switch (rrh->cause) { + case RR_REL_CAUSE_UPLINK_REJECTED: + /* Access to uplink was rejected by network or when not in group receive mode. */ + nmmh->cause = GSM48_CC_CAUSE_CALL_REJECTED; + break; + case RR_REL_CAUSE_UPLINK_BUSY: + /* Uplink was busy and did not become free. */ + nmmh->cause = GSM48_CC_CAUSE_USER_BUSY; + break; + case RR_REL_CAUSE_LINK_FAILURE: + /* Access to uplink failed. */ + nmmh->cause = GSM48_CC_CAUSE_TEMP_FAILURE; + break; + case RR_REL_CAUSE_NORMAL: + /* Uplink was released by message. */ + nmmh->cause = GSM48_CC_CAUSE_NORM_CALL_CLEAR; + break; + default: + nmmh->cause = GSM48_CC_CAUSE_NORMAL_UNSPEC; + break; + } + + gsm48_mmxx_upmsg(ms, nmsg); + return 0; +} + +/* Upper layer releases uplink. */ +static int gsm48_mm_uplink_rel_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct msgb *nmsg; + + LOGP(DMM, LOGL_INFO, "Request to release uplink, leaving group transmit mode.\n"); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + + /* Push RR header and send to RR layer. */ + return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_UPLINK_REL_REQ, 0, 0, NULL); +} + /* * other processes */ @@ -3674,15 +4122,33 @@ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE), GSM48_MMBCC_EST_REQ, gsm48_mm_init_mm_no_rr}, + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE), + GSM48_MMBCC_GROUP_REQ, gsm48_mm_group_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE), + GSM48_MMGCC_GROUP_REQ, gsm48_mm_group_req}, + /* 4.2.2.2 Attempt to update / Loc. Upd. needed */ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) | SBIT(GSM48_MM_SST_LOC_UPD_NEEDED), GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, /* emergency only */ + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE), + GSM48_MMBCC_GROUP_REQ, gsm48_mm_group_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE), + GSM48_MMGCC_GROUP_REQ, gsm48_mm_group_req}, + /* 4.2.2.3 Limited service */ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE), GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE), + GSM48_MMBCC_GROUP_REQ, gsm48_mm_group_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE), + GSM48_MMGCC_GROUP_REQ, gsm48_mm_group_req}, + /* 4.2.2.4 No IMSI */ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NO_IMSI), GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, @@ -3707,6 +4173,32 @@ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_PLMN_SEARCH), GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_no_rr}, + /* 4.2.2.7 Receiving group call, normal service */ + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL), + GSM48_MMGCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL), + GSM48_MMBCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL), + GSM48_MMGCC_UPLINK_REQ, gsm48_mm_uplink_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL), + GSM48_MMBCC_UPLINK_REQ, gsm48_mm_uplink_req}, + + /* 4.2.2.8 Receiving group call, limited service */ + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MMGCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MMBCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MMGCC_UPLINK_REQ, gsm48_mm_uplink_reject}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MMBCC_UPLINK_REQ, gsm48_mm_uplink_reject}, + /* 4.5.1.1 MM Connection (EST) */ {SBIT(GSM48_MM_ST_RR_CONN_RELEASE_NA), ALL_STATES, GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_first}, @@ -3733,10 +4225,7 @@ GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_more}, {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES, - GSM48_MMGCC_EST_REQ, gsm48_mm_init_mm_more}, - - {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE), ALL_STATES, - GSM48_MMBCC_EST_REQ, gsm48_mm_init_mm_more}, + GSM48_MMGCC_GROUP_REQ, gsm48_mm_group_req}, {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_wait}, @@ -3747,12 +4236,7 @@ {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, GSM48_MMSMS_EST_REQ, gsm48_mm_init_mm_wait}, - {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, - GSM48_MMGCC_EST_REQ, gsm48_mm_init_mm_wait}, - - {SBIT(GSM48_MM_ST_WAIT_NETWORK_CMD), ALL_STATES, - GSM48_MMBCC_EST_REQ, gsm48_mm_init_mm_wait}, - + /* Reject call in other states. */ {ALL_STATES, ALL_STATES, GSM48_MMCC_EST_REQ, gsm48_mm_init_mm_reject}, @@ -3768,6 +4252,12 @@ {ALL_STATES, ALL_STATES, GSM48_MMBCC_EST_REQ, gsm48_mm_init_mm_reject}, + {ALL_STATES, ALL_STATES, + GSM48_MMGCC_GROUP_REQ, gsm48_mm_group_reject}, + + {ALL_STATES, ALL_STATES, + GSM48_MMBCC_GROUP_REQ, gsm48_mm_group_reject}, + /* 4.5.2.1 MM Connection (DATA) */ {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE) | SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), ALL_STATES, @@ -3843,6 +4333,29 @@ {SBIT(GSM48_MM_ST_WAIT_RR_CONN_MM_CON), ALL_STATES, GSM48_MMBCC_REL_REQ, gsm48_mm_release_wait_rr}, + + /* Group transmit mode */ + {SBIT(GSM48_MM_ST_WAIT_RR_CONN_VGCS) | + SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMGCC_UPLINK_REL_REQ, gsm48_mm_uplink_rel_req}, + + {SBIT(GSM48_MM_ST_WAIT_RR_CONN_VGCS) | + SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMBCC_UPLINK_REL_REQ, gsm48_mm_uplink_rel_req}, + + {SBIT(GSM48_MM_ST_WAIT_RR_CONN_VGCS) | + SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMGCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_WAIT_RR_CONN_VGCS) | + SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMBCC_REL_REQ, gsm48_mm_group_rel_req}, + + {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMGCC_DATA_REQ, gsm48_mm_data}, + + {SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), ALL_STATES, + GSM48_MMBCC_DATA_REQ, gsm48_mm_data}, }; #define DOWNSLLEN \ @@ -3970,6 +4483,23 @@ SBIT(GSM48_MM_ST_WAIT_ADD_OUT_MM_CON), /* not supported */ GSM48_RR_ABORT_IND, gsm48_mm_abort_mm_con}, + /* Group call */ + {ALL_STATES, + GSM48_RR_GROUP_CNF, gsm48_mm_group_cnf}, + + {ALL_STATES, + GSM48_RR_UPLINK_CNF, gsm48_mm_uplink_cnf}, + + {ALL_STATES, + GSM48_RR_GROUP_REL_IND, gsm48_mm_group_rel_ind}, + + {ALL_STATES, + GSM48_RR_UPLINK_REL_IND, gsm48_mm_uplink_rel_ind}, + + {SBIT(GSM48_MM_ST_WAIT_RR_CONN_VGCS) | + SBIT(GSM48_MM_ST_MM_CONN_ACTIVE_VGCS), + GSM48_RR_REL_IND, gsm48_mm_group_rel_ind}, + /* other (also wait for network command) */ {ALL_STATES, GSM48_RR_REL_IND, gsm48_mm_rel_other}, @@ -4063,8 +4593,6 @@ struct gsm48_hdr *gh = msgb_l3(msg); uint8_t pdisc = gh->proto_discr & 0x0f; uint8_t msg_type = gh->msg_type & 0xbf; - uint8_t transaction_id; - struct gsm48_mm_conn *conn; struct gsm48_mmxx_hdr *mmh; int msg_supported = 0; /* determine, if message is supported at all */ int rr_prim = -1, rr_est = -1; /* no prim set */ @@ -4086,7 +4614,7 @@ /* pull the RR header */ msgb_pull(msg, sizeof(struct gsm48_rr_hdr)); - /* create transaction (if not exists) and push MM header to message */ + /* create transaction (if not exists) and push message */ switch (pdisc) { case GSM48_PDISC_CC: rr_prim = GSM48_MMCC_DATA_IND; @@ -4106,56 +4634,57 @@ case GSM48_PDISC_BCAST_CC: rr_prim = GSM48_MMBCC_DATA_IND; break; - default: - LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n", - pdisc); - msgb_free(msg); - return gsm48_mm_tx_mm_status(ms, - GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED); } + if (rr_prim != -1) { + uint8_t transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */ + uint32_t callref; + struct gsm48_mm_conn *conn; - transaction_id = ((gh->proto_discr & 0xf0) ^ 0x80) >> 4; /* flip */ + if (mm->vgcs) { + /* Ongoing group call. */ + callref = mm->vgcs_callref; + } else { + /* find transaction, if any */ + conn = mm_conn_by_id(mm, pdisc, transaction_id); - /* find transaction, if any */ - conn = mm_conn_by_id(mm, pdisc, transaction_id); - - /* create MM connection instance */ - if (!conn) { - /* if MT calls are not supported with protocol */ - if (rr_est == -1) { - LOGP(DMM, LOGL_ERROR, "No MO connection for pdisc=%d, " - "transaction_id=%d\n", pdisc, transaction_id); - msgb_free(msg); - return -EINVAL; + /* create MM connection instance */ + if (!conn) { + /* if MT calls are not supported with protocol */ + if (rr_est == -1) { + LOGP(DMM, LOGL_ERROR, "No MO connection for pdisc=%d, transaction_id=%d\n", + pdisc, transaction_id); + msgb_free(msg); + return -EINVAL; + } + conn = mm_conn_new(mm, pdisc, transaction_id, sapi, mm_conn_new_ref++); + rr_prim = rr_est; + } + if (!conn) { + msgb_free(msg); + return -ENOMEM; + } + callref = conn->ref; } - conn = mm_conn_new(mm, pdisc, transaction_id, sapi, - mm_conn_new_ref++); - if (!conn) { - msgb_free(msg); - return -ENOMEM; + /* push new header */ + msgb_push(msg, sizeof(struct gsm48_mmxx_hdr)); + mmh = (struct gsm48_mmxx_hdr *)msg->data; + mmh->msg_type = rr_prim; + mmh->ref = callref; + mmh->transaction_id = transaction_id; + mmh->sapi = sapi; + + /* go MM CONN ACTIVE state */ + if (mm->state == GSM48_MM_ST_WAIT_NETWORK_CMD + || mm->state == GSM48_MM_ST_RR_CONN_RELEASE_NA) { + /* stop RR release timer */ + stop_mm_t3240(mm); + + /* stop "RR connection release not allowed" timer */ + stop_mm_t3241(mm); + + new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0); } - rr_prim = rr_est; - } - - /* push new header */ - msgb_push(msg, sizeof(struct gsm48_mmxx_hdr)); - mmh = (struct gsm48_mmxx_hdr *)msg->data; - mmh->msg_type = rr_prim; - mmh->ref = conn->ref; - mmh->transaction_id = conn->transaction_id; - mmh->sapi = conn->sapi; - - /* go MM CONN ACTIVE state */ - if (mm->state == GSM48_MM_ST_WAIT_NETWORK_CMD - || mm->state == GSM48_MM_ST_RR_CONN_RELEASE_NA) { - /* stop RR release timer */ - stop_mm_t3240(mm); - - /* stop "RR connection release not allowed" timer */ - stop_mm_t3241(mm); - - new_mm_state(mm, GSM48_MM_ST_MM_CONN_ACTIVE, 0); } /* forward message */ @@ -4190,6 +4719,13 @@ rc = -ENOTSUP; msgb_free(msg); return rc; + + default: + LOGP(DMM, LOGL_NOTICE, "Protocol type 0x%02x unsupported.\n", + pdisc); + msgb_free(msg); + return gsm48_mm_tx_mm_status(ms, + GSM48_REJECT_MSG_TYPE_NOT_IMPLEMENTED); } LOGP(DMM, LOGL_INFO, "(ms %s) Received '%s' in MM state %s\n", ms->name, @@ -4268,6 +4804,9 @@ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_NORMAL_SERVICE), GSM48_MM_EVENT_IMSI_DETACH, gsm48_mm_imsi_detach_start}, + /* 4.2.2.7 Receiving Group Call (Normal service) */ + // nothing here + /* 4.2.2.2 Attempt to update / Loc. upd. needed */ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_ATTEMPT_UPDATE) | SBIT(GSM48_MM_SST_LOC_UPD_NEEDED), @@ -4303,6 +4842,9 @@ {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_LIMITED_SERVICE), GSM48_MM_EVENT_TIMEOUT_T3212, gsm48_mm_loc_upd_delay_per}, /* 4.4.2 */ + /* 4.2.2.8 Receiving Group Call (Limited service) */ + // nothing here + /* 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), @@ -4398,6 +4940,17 @@ {ALL_STATES, ALL_STATES, GSM48_MM_EVENT_CLASSMARK_CHG, gsm48_mm_classm_chg}, #endif + + /* Group call notification event */ + {ALL_STATES, ALL_STATES, + GSM48_MM_EVENT_NOTIFICATION, gsm48_mm_notification}, + + /* Uplink free/busy while in group receive mode */ + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL) | SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MM_EVENT_UPLINK_BUSY, gsm48_mm_uplink_free}, + + {SBIT(GSM48_MM_ST_MM_IDLE), SBIT(GSM48_MM_SST_RX_VGCS_NORMAL) | SBIT(GSM48_MM_SST_RX_VGCS_LIMITED), + GSM48_MM_EVENT_UPLINK_FREE, gsm48_mm_uplink_free}, }; #define EVENTSLLEN \ -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34492?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I05957182a57423ad947ab200b52f65fde859e110 Gerrit-Change-Number: 34492 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[XL] Change in osmocom-bb[master]: ASCI: Add group receive and transmit mode support to RR layer
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34491?usp=email
) Change subject: ASCI: Add group receive and transmit mode support to RR layer ...................................................................... ASCI: Add group receive and transmit mode support to RR layer Related: OS#5364 Change-Id: Ia55c182a1b4cde777a0e16dcfe0cd32e0f2e38eb --- M src/host/layer23/include/osmocom/bb/common/settings.h M src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h M src/host/layer23/src/mobile/gsm48_rr.c 3 files changed, 1,384 insertions(+), 87 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/91/34491/1 diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h index 52b485d..efdc69a 100644 --- a/src/host/layer23/include/osmocom/bb/common/settings.h +++ b/src/host/layer23/include/osmocom/bb/common/settings.h @@ -188,6 +188,9 @@ /* Timeout for GSM 03.22 C7 state */ uint8_t any_timeout; + + /* ASCI settings */ + bool uplink_release_local; }; struct gsm_settings_abbrev { diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h index 9b73ab2..fdfb144 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h @@ -10,6 +10,9 @@ #define T200_DCCH_SHARED 2 /* SDCCH shares SAPI 0 and 3 */ #define T200_ACCH 2 /* SACCH SAPI 3 */ +/* GSM 04.08 RR timers */ +#define GSM_T3128_MS 1, 0 /* Uplink investigation timer. */ +#define GSM_T3130_MS 5, 0 /* Uplink access timeout. */ /* GSM 04.07 9.1.2 */ #define GSM48_RR_EST_REQ 0x10 @@ -23,6 +26,15 @@ #define GSM48_RR_ABORT_REQ 0x60 #define GSM48_RR_ABORT_IND 0x62 #define GSM48_RR_ACT_REQ 0x70 +/* These are non-stadard primitives, used for group receive/transmit modes. */ +#define GSM48_RR_GROUP_REQ 0x80 /* Join a group channel in group receive mode. */ +#define GSM48_RR_GROUP_CNF 0x81 /* Group channel has been joined. */ +#define GSM48_RR_GROUP_REL_REQ 0x84 /* Release group channel. */ +#define GSM48_RR_GROUP_REL_IND 0x86 /* Group channel has been released or failed. */ +#define GSM48_RR_UPLINK_REQ 0x90 /* Request uplink for group transmit mode. */ +#define GSM48_RR_UPLINK_CNF 0x91 /* Access granted. */ +#define GSM48_RR_UPLINK_REL_REQ 0x94 /* Release uplink for group receive mode. */ +#define GSM48_RR_UPLINK_REL_IND 0x96 /* Access denied or failed or uplink released. */ #define RR_EST_CAUSE_EMERGENCY 1 #define RR_EST_CAUSE_REESTAB_TCH_F 2 @@ -45,6 +57,8 @@ #define RR_REL_CAUSE_EMERGENCY_ONLY 6 #define RR_REL_CAUSE_LOST_SIGNAL 7 #define RR_REL_CAUSE_LINK_FAILURE 8 +#define RR_REL_CAUSE_UPLINK_BUSY 9 +#define RR_REL_CAUSE_UPLINK_REJECTED 10 #define RR_SYNC_CAUSE_CIPHERING 1 @@ -71,6 +85,11 @@ #define GSM48_RR_ST_DEDICATED 2 #define GSM48_RR_ST_REL_PEND 3 +/* group states */ +#define GSM48_RR_GST_OFF 0 +#define GSM48_RR_GST_RECEIVE 1 +#define GSM48_RR_GST_TRANSMIT 2 + /* special states for SAPI 3 link */ #define GSM48_RR_SAPI3ST_IDLE 0 #define GSM48_RR_SAPI3ST_WAIT_EST 1 @@ -197,6 +216,19 @@ /* sapi 3 */ uint8_t sapi3_state; uint8_t sapi3_link_id; + + /* group call */ + struct llist_head notif_list; /* list of received call notifications */ + int group_state; /* extension to RR state for group transmit/receive modes */ + struct gsm48_rr_cd cd_group; /* channel description of group call channel */ + bool uplink_free; /* Is set, if uplink is currently free. */ + int8_t uic; /* UIC to use for access burst (-1 for BSIC) */ + bool uplink_access; /* The network wants us to send listener access bursts. */ + struct osmo_timer_list t_ul_free; /* Uplink free timer. (480ms timer) */ + struct osmo_timer_list t3128; /* Uplink investigation timer. */ + struct osmo_timer_list t3130; /* Uplink access timer. */ + int uplink_tries; /* Counts number of tries to access the uplink. */ + int uplink_counter; /* Counts number of access bursts per 'try'. */ }; const char *get_rr_name(int value); diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 47817a7..bb453f1 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -34,6 +34,53 @@ * When the assignment or handover fails, the old channel is activate and the * link is established again. Also pending messages are sent. * + * Group Channel: + * + * A group receive/transmit mode is not documented at GSM 04.07. The group + * receive mode is similar to the IDLE mode, except that the MS is listening + * to a TCH. The group transmit mode is similar to the DEDICATED mode. Special + * (undocumented) commands are used to enter group receive and transmit mode. + * + * There is a substate that indicates group receive/transmit mode. If the + * substate is set to group receive, the IDLE mode becomes the group receive + * mode. If the substate is set to group transmit, the dedicated mode becomes + * the group transmit mode. The substate set to group receive allows to enter + * regular dedicated mode and return back to group receive mode afterwards. + * + * new_rr_state(rr, GSM48_RR_ST_IDLE) is used to return to IDLE mode or to + * group receive mode, depending on the substate. + * + * The Uplink access on group channel: + * + * If the uplink is busy, wait until it becomes free (Uplink investigation + * procedure). Abort, if the procedure times out, if the VGCS UPLINK GRANT + * message is recived for a different talker. + * + * Request uplink using access bursts on TCH until an VGCS UPLINK GRANT is + * received. Abort, if it the procedure times out, if the uplink becomes busy, + * if the VGCS UPLINK GRANT message references a different frame numer. + * + * Establish layer 2 with TALKER INDICATION. Abort, if content resolution + * mismatches (RR_REL_IND), if link fails (MDL_ERROR), if uplink becomes free. + * + * Release uplink and wait until uplink becomes free. Abort, if UPLINK RELEASE + * is received or if uplink fails. + * + * New primitives are invented for group/broadcast calls. They are not + * specified in any recommendation. They are: + * + * GSM48_MM_EVENT_NOTIFICATION: Notify MM layer about received/ceased call. + * GSM48_MM_EVENT_UPLINK_BUSY: Notify MM layer about uplink becoming busy. + * GSM48_MM_EVENT_UPLINK_FREE: Notify MM layer about uplink becoming free. + * + * RR_GROUP_REQ: The MM layer requests group channel in receive mode. + * RR_GROUP_CNF: The RR confirms group channel. + * RR_GROUP_REL_REQ: The MM layer releases group channel. + * RR_GROUP_REL_IND: The RR indicates/confirms release of group channel. + * RR_UPLINK_REQ: The MM layer requests uplink (group transmit mode). + * RR_UPLINK_CNF: The RR layer confirms uplink. (Uplink was granted.) + * RR_UPLINK_REL_REQ: The MM layer requests release of uplink. + * RR_UPLINK_REL_IND: The RR layer indicates/confirms release of uplink */ /* Testing delayed (immediate) assignment / handover @@ -84,6 +131,8 @@ #include <l1ctl_proto.h> +static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd, uint16_t *ma, uint8_t *ma_len); +static int gsm48_rr_activate_channel(struct osmocom_ms *ms, struct gsm48_rr_cd *cd, uint16_t *ma, uint8_t ma_len); static void start_rr_t_meas(struct gsm48_rrlayer *rr, int sec, int micro); static void stop_rr_t_starting(struct gsm48_rrlayer *rr); static void stop_rr_t3124(struct gsm48_rrlayer *rr); @@ -93,6 +142,13 @@ static int gsm48_rr_set_mode(struct osmocom_ms *ms, uint8_t chan_nr, uint8_t mode, uint8_t tch_flags); static int gsm48_rr_rel_cnf(struct osmocom_ms *ms, struct msgb *msg); int gsm414_rcv_test(struct osmocom_ms *ms, const struct msgb *msg); +static int gsm48_rr_uplink_access(struct osmocom_ms *ms, struct msgb *msg); +static int gsm48_rr_uplink_access_abort(struct osmocom_ms *ms, uint8_t cause); +static int gsm48_rr_group_rel(struct osmocom_ms *ms, int cause); +static int gsm48_rr_uplink_rel_req(struct osmocom_ms *ms, struct msgb *msg); +static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref, int hist_num); +static int gsm48_rr_tx_talker_indication(struct osmocom_ms *ms); +static int gsm48_rr_uplink_status(struct osmocom_ms *ms, uint32_t event); /* * support @@ -348,19 +404,21 @@ static void new_rr_state(struct gsm48_rrlayer *rr, int state) { + struct osmocom_ms *ms = rr->ms; + if (state < 0 || state >= (sizeof(gsm48_rr_state_names) / sizeof(char *))) return; - /* must check against equal state */ - if (rr->state == state) { + /* Check against equal state or IDLE state. */ + if (rr->state == state && state != GSM48_RR_ST_IDLE) { LOGP(DRR, LOGL_INFO, "equal state ? %s\n", gsm48_rr_state_names[rr->state]); return; } LOGP(DRR, LOGL_INFO, "new state %s -> %s\n", - gsm48_rr_state_names[rr->state], gsm48_rr_state_names[state]); + gsm48_rr_state_names[rr->state], gsm48_rr_state_names[state]); /* abort handover, in case of release of dedicated mode */ if (rr->state == GSM48_RR_ST_DEDICATED) { @@ -374,10 +432,15 @@ rr->state = state; - if (state == GSM48_RR_ST_IDLE) { + if (state != GSM48_RR_ST_IDLE) + return; + + /* Return from dedicated/group receive/transmit mode to idle mode. (Trigger cell reselection.) */ + if (rr->group_state == GSM48_RR_GST_OFF) { struct msgb *msg, *nmsg; struct gsm322_msg *em; + LOGP(DRR, LOGL_INFO, "Returning to IDLE mode.\n"); /* release dedicated mode, if any */ l1ctl_tx_dm_rel_req(rr->ms); rr->ms->meas.rl_fail = 0; @@ -420,6 +483,45 @@ msgb_free(nmsg); /* reset any BA range */ rr->ba_ranges = 0; + return; + } + + /* Return from dedicated mode to group receive mode. + * This is not used, because we never enter dedicated mode during group receive/transmit mode. + * It may be used later, if we support it in MM layer. */ + if (rr->group_state == GSM48_RR_GST_RECEIVE) { + uint16_t ma[64]; + uint8_t ma_len; + struct msgb *msg; + + LOGP(DRR, LOGL_INFO, "Returning to GROUP RECEIVE mode.\n"); + /* release dedicated mode, if any */ + l1ctl_tx_dm_rel_req(rr->ms); + rr->ms->meas.rl_fail = 0; + rr->dm_est = 0; + l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_SCHED); + /* free establish message, if any */ + rr->rr_est_req = 0; + if (rr->rr_est_msg) { + msgb_free(rr->rr_est_msg); + rr->rr_est_msg = NULL; + } + /* free all pending messages */ + while((msg = msgb_dequeue(&rr->downqueue))) + msgb_free(msg); + /* reset ciphering */ + rr->cipher_on = 0; + /* copy channel description "group mode" */ + memcpy(&rr->cd_now, &rr->cd_group, sizeof(rr->cd_now)); + /* render channel "group mode" */ + gsm48_rr_render_ma(ms, &rr->cd_now, ma, &ma_len); + /* activate channel */ + gsm48_rr_activate_channel(ms, &rr->cd_now, ma, ma_len); +#ifdef WITH_GAPK_IO + /* clean-up GAPK state */ + gapk_io_clean_up_ms(rr->ms); +#endif + return; } } @@ -460,6 +562,14 @@ { GSM48_RR_ABORT_REQ, "RR_ABORT_REQ" }, { GSM48_RR_ABORT_IND, "RR_ABORT_IND" }, { GSM48_RR_ACT_REQ, "RR_ACT_REQ" }, + { GSM48_RR_GROUP_REQ, "RR_GROUP_REQ" }, + { GSM48_RR_GROUP_CNF, "RR_GROUP_CNF" }, + { GSM48_RR_GROUP_REL_REQ, "RR_GROUP_REL_REQ" }, + { GSM48_RR_GROUP_REL_IND, "RR_GROUP_REL_IND" }, + { GSM48_RR_UPLINK_REQ, "RR_UPLINK_REQ" }, + { GSM48_RR_UPLINK_CNF, "RR_UPLINK_CNF" }, + { GSM48_RR_UPLINK_REL_REQ, "RR_UPLINK_REL_REQ" }, + { GSM48_RR_UPLINK_REL_IND, "RR_UPLINK_REL_IND" }, { 0, NULL } }; @@ -778,6 +888,36 @@ new_rr_state(rr, GSM48_RR_ST_IDLE); } +static void timeout_rr_t3128(void *arg) +{ + struct gsm48_rrlayer *rr = arg; + struct osmocom_ms *ms = rr->ms; + + LOGP(DRR, LOGL_INFO, "timer T3128 has fired\n"); + + LOGP(DRR, LOGL_NOTICE, "Failed to access uplink, uplink did not become free.\n"); + gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_UPLINK_BUSY); +} + +static void timeout_rr_t3130(void *arg) +{ + struct gsm48_rrlayer *rr = arg; + struct osmocom_ms *ms = rr->ms; + + LOGP(DRR, LOGL_INFO, "timer T3130 has fired\n"); + + gsm48_rr_uplink_access(ms, NULL); +} + +static void timeout_rr_t_ul_free(void *arg) +{ + struct gsm48_rrlayer *rr = arg; + + LOGP(DRR, LOGL_INFO, "uplink free timer has fired\n"); + rr->uplink_free = false; + gsm48_rr_uplink_status(rr->ms, GSM48_MM_EVENT_UPLINK_BUSY); +} + static void start_rr_t_meas(struct gsm48_rrlayer *rr, int sec, int micro) { rr->t_meas.cb = timeout_rr_meas; @@ -830,6 +970,33 @@ osmo_timer_schedule(&rr->t3126, sec, micro); } +static void start_rr_t3128(struct gsm48_rrlayer *rr, int sec, int micro) +{ + LOGP(DRR, LOGL_INFO, "starting T3128 with %d.%03d seconds\n", sec, + micro / 1000); + rr->t3128.cb = timeout_rr_t3128; + rr->t3128.data = rr; + osmo_timer_schedule(&rr->t3128, sec, micro); +} + +static void start_rr_t3130(struct gsm48_rrlayer *rr, int sec, int micro) +{ + LOGP(DRR, LOGL_INFO, "starting T3130 with %d.%03d seconds\n", sec, + micro / 1000); + rr->t3130.cb = timeout_rr_t3130; + rr->t3130.data = rr; + osmo_timer_schedule(&rr->t3130, sec, micro); +} + +static void start_rr_t_ul_free(struct gsm48_rrlayer *rr) +{ + if (!osmo_timer_pending(&rr->t_ul_free)) + LOGP(DRR, LOGL_INFO, "starting uplink free timer\n"); + rr->t_ul_free.cb = timeout_rr_t_ul_free; + rr->t_ul_free.data = rr; + osmo_timer_schedule(&rr->t_ul_free, 0, 480000); +} + static void stop_rr_t_meas(struct gsm48_rrlayer *rr) { if (osmo_timer_pending(&rr->t_meas)) { @@ -886,6 +1053,30 @@ } } +static void stop_rr_t3128(struct gsm48_rrlayer *rr) +{ + if (osmo_timer_pending(&rr->t3128)) { + LOGP(DRR, LOGL_INFO, "stopping pending timer T3128\n"); + osmo_timer_del(&rr->t3128); + } +} + +static void stop_rr_t3130(struct gsm48_rrlayer *rr) +{ + if (osmo_timer_pending(&rr->t3130)) { + LOGP(DRR, LOGL_INFO, "stopping pending timer T3130\n"); + osmo_timer_del(&rr->t3130); + } +} + +static void stop_rr_t_ul_free(struct gsm48_rrlayer *rr) +{ + if (osmo_timer_pending(&rr->t_ul_free)) { + LOGP(DRR, LOGL_INFO, "stopping pending uplink free timer\n"); + osmo_timer_del(&rr->t_ul_free); + } +} + /* * status */ @@ -1284,6 +1475,558 @@ } /* + * VGCS uplink control + */ + +/* UPLINK BUSY (9.1.46) */ +static int gsm48_rr_rx_uplink_busy(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + + LOGP(DRR, LOGL_INFO, "UPLINK BUSY\n"); + + /* Only allow when in some group mode. */ + if (rr->group_state == GSM48_RR_GST_OFF) + return 0; + + /* Uplink is busy now. */ + if (rr->uplink_free) { + rr->uplink_free = false; + gsm48_rr_uplink_status(ms, GSM48_MM_EVENT_UPLINK_BUSY); + } + stop_rr_t_ul_free(rr); + + /* Abort during uplink investigation or access procedure. */ + if (osmo_timer_pending(&rr->t3128) || osmo_timer_pending(&rr->t3130)) { + LOGP(DRR, LOGL_NOTICE, "Abort uplink access, due to busy uplink.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_UPLINK_BUSY); + } + + return 0; +} + +/* UPLINK FREE (9.1.47) */ +static int gsm48_rr_rx_uplink_free(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct bitvec bv; + bool uplink_access = false; + int8_t uic = -1; + uint8_t *mode; + bool group_channel; + + bv = (struct bitvec) { + .data_len = msgb_l3len(msg), + .data = msgb_l3(msg), + .cur_bit = 8, + }; + + /* Uplink Access */ + if (bitvec_get_bit_high(&bv) == H) + uplink_access = true; + + /* UIC */ + if (bitvec_get_bit_high(&bv) == H) { + uic = bitvec_get_uint(&bv, 6); + } + + /* Note: Emergency Indicator not used. */ + + /* Do not flood the logging with UPLINK FREE messages. Log only on the fist received message. */ + if (!osmo_timer_pending(&rr->t_ul_free)) + LOGP(DRR, LOGL_INFO, "UPLINK FREE (uplink access=%s, uic=%d)\n", (uplink_access) ? "true" : "false", + uic); + + /* Uplink is free now. */ + if (!rr->uplink_free) { + rr->uplink_free = true; + gsm48_rr_uplink_status(ms, GSM48_MM_EVENT_UPLINK_FREE); + } + rr->uic = uic; + rr->uplink_access = uplink_access; + start_rr_t_ul_free(rr); + + /* We can be in group mode or in dedicated mode. When we are in dedicated mode and we receive UPLINK FREE, + * we know that we are actually on a group channel. This is the actual confirm to the UPLINK RELEASE message + * on a group channel. We must then release layer 2 locally and indicate channel release toward upper layer. + * + * When we are in group transmit mode, we return to group receive mode and also release layer 2 locally and + * indicate uplink release towards upper layer. + * + * When we are waiting for a free uplink (T3128 is running), we start uplink access. While accessing the + * uplink, we ignore further UPLINK FREE messages. + */ + group_channel = (rr->group_state != GSM48_RR_GST_OFF); + + if (group_channel) { + /* Start uplink access. */ + if (osmo_timer_pending(&rr->t3128)) { + rr->uplink_tries = 3; + return gsm48_rr_uplink_access(ms, NULL); + } + + /* Ignore uplink free messages while accessing uplink. */ + if (osmo_timer_pending(&rr->t3130)) + return 0; + } + + /* Any time in group transmit mode or dedicated mode, release on uplink free. */ + if (rr->state == GSM48_RR_ST_DEDICATED || rr->state == GSM48_RR_ST_REL_PEND) { + struct msgb *nmsg; + + LOGP(DRR, LOGL_INFO, "Uplink becomes free, send (local) release to layer 2.\n"); + + /* Go into pending release state if not already. + * We are already in pending relese state when we release uplink normally. + * If we receive UPLINK FREE while we release normally, we abort layer 2. */ + if (rr->state != GSM48_RR_ST_REL_PEND) + new_rr_state(rr, GSM48_RR_ST_REL_PEND); + + /* release message */ + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + mode = msgb_put(nmsg, 2); + mode[0] = RSL_IE_RELEASE_MODE; + mode[1] = RSL_REL_LOCAL_END; + gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0); + + return 0; + } + + return 0; +} + +/* UPLINK RELEASE (9.1.48) */ +static int gsm48_rr_rx_uplink_release(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm48_hdr *gh = msgb_l3(msg); + struct gsm48_uplink_release *ur = (struct gsm48_uplink_release *)gh->data; + int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*ur); + + if (payload_len < 0) { + LOGP(DRR, LOGL_NOTICE, "Short UPLINK RELEASE message.\n"); + return -EINVAL; + } + + LOGP(DRR, LOGL_INFO, "UPLINK RELEASE with cause 0x%02x\n", ur->rr_cause); + + /* Only allow when in some group mode. */ + if (rr->group_state == GSM48_RR_GST_OFF) + return 0; + + if (rr->state == GSM48_RR_ST_DEDICATED && rr->group_state == GSM48_RR_GST_TRANSMIT) + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_NORMAL); + + return 0; +} + +/* Release of channel on VGCS/VBS. */ +static int gsm48_rr_rx_chan_rel_ui(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm48_hdr *gh = msgb_l3(msg); + struct gsm48_chan_rel *cr = (struct gsm48_chan_rel *)gh->data; + int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*cr); + struct tlv_parsed tp; + + if (payload_len < 0) { + LOGP(DRR, LOGL_NOTICE, "Short read of CHANNEL RELEASE " + "message.\n"); + return gsm48_rr_tx_rr_status(ms, + GSM48_RR_CAUSE_PROT_ERROR_UNSPC); + } + tlv_parse(&tp, &gsm48_rr_att_tlvdef, cr->data, payload_len, 0, 0); + + LOGP(DRR, LOGL_INFO, "CHANNEL RELESE via UI frame with cause 0x%02x\n", cr->rr_cause); + + /* Only allow when in group receive mode. */ + if (rr->group_state != GSM48_RR_GST_RECEIVE) + return 0; + + return gsm48_rr_group_rel(ms, RR_REL_CAUSE_NORMAL); +} + +/* VGCS UPLINK GRANT (9.1.49) */ +static int gsm48_rr_rx_vgcs_uplink_grant(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm48_sysinfo *s = &ms->cellsel.sel_si; + struct gsm_settings *set = &ms->settings; + struct gsm0408_vgcs_ul_grant *ug = msgb_l3(msg); + int ug_len = msgb_l3len(msg) - sizeof(*ug); + + LOGP(DRR, LOGL_INFO, "VGCS UPLINK GRANT\n"); + + if (ug_len < 0) { + LOGP(DRR, LOGL_NOTICE, "Short read of VGCS UPLINK GRANT message.\n"); + return -EINVAL; + } + + /* Only allow when in some group mode. */ + if (rr->group_state == GSM48_RR_GST_OFF) + return 0; + + /* Uplink is busy now. */ + if (rr->uplink_free) { + rr->uplink_free = false; + gsm48_rr_uplink_status(rr->ms, GSM48_MM_EVENT_UPLINK_BUSY); + } + stop_rr_t_ul_free(rr); + + /* Abort during uplink investigation or access procedure. */ + if (osmo_timer_pending(&rr->t3128)) { + LOGP(DRR, LOGL_NOTICE, "Abort uplink access, other phone accessing the uplink.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_UPLINK_BUSY); + } + + /* We are not waiting for the uplink to be granted. */ + if (!osmo_timer_pending(&rr->t3130)) + return 0; + + /* Stop timer. */ + stop_rr_t3130(rr); + + /* Check if message is for our request. */ + if (!gsm48_match_ra(ms, &ug->req_ref, 5)) { + LOGP(DRR, LOGL_NOTICE, "Abort uplink access, other phone gets uplink access granted.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_UPLINK_BUSY); + } + + LOGP(DRR, LOGL_INFO, "Access to uplink has been granted.\n"); + + /* Set initial power and timing advance. */ + rr->cd_now.ind_tx_power = s->ms_txpwr_max_cch; + rr->cd_now.ind_ta = ug->ta; + LOGP(DRR, LOGL_INFO, "Applying initial ta and tx_power\n"); + l1ctl_tx_param_req(ms, rr->cd_now.ind_ta - set->alter_delay, + (set->alter_tx_power) ? set->alter_tx_power_value : s->ms_txpwr_max_cch); + + /* Turn on transmitter. */ + rr->cd_now.tch_flags &= ~(L1CTL_TCH_FLAG_RXONLY); + gsm48_rr_set_mode(ms, rr->cd_now.chan_nr, rr->cd_now.mode, rr->cd_now.tch_flags); + + /* Complete group transmit mode. */ + new_rr_state(rr, GSM48_RR_ST_DEDICATED); + + /* Establish layer 2 connection. */ + return gsm48_rr_tx_talker_indication(ms); +} + +/* send rr uplink release */ +static int gsm48_rr_tx_uplink_release(struct osmocom_ms *ms, uint8_t cause) +{ + struct msgb *nmsg; + struct gsm48_hdr *gh; + struct gsm48_uplink_release *ur; + + LOGP(DRR, LOGL_INFO, "UPLINK RELEASE (cause #%d)\n", cause); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); + ur = (struct gsm48_uplink_release *) msgb_put(nmsg, sizeof(*ur)); + + gh->proto_discr = GSM48_PDISC_RR; + gh->msg_type = GSM48_MT_RR_UPLINK_RELEASE; + ur->rr_cause = cause; + + return gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0); +} + +/* send talker indication */ +static int gsm48_rr_tx_talker_indication(struct osmocom_ms *ms) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; + struct gsm48_hdr *gh; + struct gsm48_talker_indication *ti; + + LOGP(DRR, LOGL_INFO, "TALKER INDICATION\n"); + + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + gh = (struct gsm48_hdr *) msgb_put(nmsg, sizeof(*gh)); + ti = (struct gsm48_talker_indication *) msgb_put(nmsg, sizeof(*ti)); + + gh->proto_discr = GSM48_PDISC_RR; + gh->msg_type = GSM48_MT_RR_TALKER_IND; + + /* classmark 2 */ + ti->cm2_len = sizeof(ti->cm2); + gsm48_rr_enc_cm2(ms, &ti->cm2, rr->cd_now.arfcn); + /* mobile identity (Use TMSI if available.) */ + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_TMSI, false); + + /* start establishmnet */ + return gsm48_send_rsl(ms, RSL_MT_EST_REQ, nmsg, 0); +} + +struct asci_notif { + struct llist_head entry; + struct gsm48_rrlayer *rr; + uint8_t gcr[5]; + bool ch_desc_present; + struct gsm48_chan_desc ch_desc; + struct osmo_timer_list timer; +}; + +/* When does a notification received from NCH expires. */ +#define NOTIFICATION_TIMEOUT 5 + +static void asci_notif_timeout(void *arg); + +/* Add new notification to list. */ +static struct asci_notif *asci_notif_alloc(struct gsm48_rrlayer *rr, uint8_t *gcr) +{ + struct asci_notif *notif; + + notif = talloc_zero(rr->ms, struct asci_notif); + if (!notif) + return NULL; + notif->rr = rr; + memcpy(notif->gcr, gcr, sizeof(notif->gcr)); + llist_add_tail(¬if->entry, &rr->notif_list); + + notif->timer.cb = asci_notif_timeout; + notif->timer.data = notif; + + return notif; +} + +/* Remove notification from list. */ +static void asci_notif_free(struct asci_notif *notif) +{ + osmo_timer_del(¬if->timer); + llist_del(¬if->entry); + talloc_free(notif); +} + +/* Remove all ASCI notifications from list. */ +static void asci_notif_list_free(struct gsm48_rrlayer *rr) +{ + struct asci_notif *notif, *notif2; + + llist_for_each_entry_safe(notif, notif2, &rr->notif_list, entry) + asci_notif_free(notif); +} + +/* Notification timed out. */ +static void asci_notif_timeout(void *arg) +{ + struct asci_notif *notif = arg; + struct gsm48_rrlayer *rr = notif->rr; + struct msgb *nmsg; + struct gsm48_mm_event *mme; + + /* Send notification of ceased call to MM layer. */ + LOGP(DRR, LOGL_INFO, "Notify MM layer about ceased group call.\n"); + nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_NOTIFICATION); + if (!nmsg) + return; + mme = (struct gsm48_mm_event *) nmsg->data; + memcpy(mme->notification.gcr, notif->gcr, sizeof(mme->notification.gcr)); + mme->notification.gone = true; + gsm48_mmevent_msg(rr->ms, nmsg); + + asci_notif_free(notif); +} + +/* Find notification in list. */ +static struct asci_notif *asci_notif_find(struct gsm48_rrlayer *rr, uint8_t *gcr) +{ + struct asci_notif *notif; + + llist_for_each_entry(notif, &rr->notif_list, entry) { + if (!memcmp(¬if->gcr, gcr, sizeof(notif->gcr))) + return notif; + } + + return NULL; +} + +static int gsm48_rr_rx_group_call(struct osmocom_ms *ms, uint8_t *gcr, uint8_t *ch_desc, bool nch) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct asci_notif *notif; + bool update_call = false; + struct msgb *nmsg; + struct gsm48_mm_event *mme; + + /* Find or create notification entry. Only create entries for notifications on NCH */ + notif = asci_notif_find(rr, gcr); + if (!notif) { + update_call = true; + if (nch) { + notif = asci_notif_alloc(rr, gcr); + if (!notif) + return -ENOMEM; + } + } + + /* Update channel description. */ + if (notif) { + if (ch_desc) { + if (!notif->ch_desc_present) + update_call = true; + notif->ch_desc_present = true; + memcpy(¬if->ch_desc, ch_desc, sizeof(notif->ch_desc)); + } else { + notif->ch_desc_present = false; + if (!notif->ch_desc_present) + update_call = true; + } + /* (Re-)Start timer. */ + osmo_timer_schedule(¬if->timer, NOTIFICATION_TIMEOUT, 0); + } else + update_call = true; + + /* Send notification of new or updated call to MM layer. */ + if (update_call) { + LOGP(DRR, LOGL_INFO, "Notify MM layer about new/updated group call.\n"); + nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_NOTIFICATION); + if (!nmsg) + return -ENOMEM; + mme = (struct gsm48_mm_event *) nmsg->data; + memcpy(mme->notification.gcr, gcr, sizeof(mme->notification.gcr)); + if (ch_desc) { + mme->notification.ch_desc_present = true; + memcpy(&mme->notification.ch_desc, ch_desc, sizeof(mme->notification.ch_desc)); + } + gsm48_mmevent_msg(ms, nmsg); + } + + return 0; +} + +/* Common function to decode Group Call Information */ +static int gsm48_rr_decode_group_call_info(struct osmocom_ms *ms, struct bitvec *bv, bool nch) +{ + struct bitvec *gcr_bv = NULL, *chd_bv = NULL; + int rc = 0; + int i; + + /* <Group Call Reference : bit(36)> */ + gcr_bv = bitvec_alloc(5*8, NULL); + OSMO_ASSERT(gcr_bv); + for (i = 0; i < 36; i++) + bitvec_set_bit(gcr_bv, bitvec_get_bit_pos(bv, bv->cur_bit++)); + /* Group Channel Description */ + if (bitvec_get_bit_pos(bv, bv->cur_bit++) == 1) { + chd_bv = bitvec_alloc(3*8, NULL); + OSMO_ASSERT(chd_bv); + for (i = 0; i < 24; i++) + bitvec_set_bit(chd_bv, bitvec_get_bit_pos(bv, bv->cur_bit++)); + /* FIXME: hopping */ + if (bitvec_get_bit_pos(bv, bv->cur_bit++) == 1) { + LOGP(DRR, LOGL_ERROR, "\nHopping not supported on VGCS/VBS channel, please fix!\n\n"); + rc = -ENOTSUP; + goto out; + } + } + + rc = gsm48_rr_rx_group_call(ms, gcr_bv->data, (chd_bv) ? chd_bv->data : NULL, nch); + +out: + if (chd_bv) + bitvec_free(chd_bv); + if (gcr_bv) + bitvec_free(gcr_bv); + + return rc; +} + +/* Notification/FACCH (9.1.21a) */ +static int gsm48_rr_rx_notif_facch(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_hdr_sh *sgh = msgb_l3(msg); + int payload_len = msgb_l3len(msg) - sizeof(*sgh); + struct bitvec bv; + int rc; + + LOGP(DRR, LOGL_INFO, "NOTIFICATION/FACCH\n"); + + bv = (struct bitvec) { + .data = sgh->data, + .data_len = payload_len, + }; + + /* Group Call Information */ + if (bitvec_get_bit_pos(&bv, bv.cur_bit++) == 0) { + rc = gsm48_rr_decode_group_call_info(ms, &bv, false); + return rc; + } + + /* Note: Other informations are not used. */ + return -ENOTSUP; +} + +/* Notification/NCH (9.1.21b) */ +static int gsm48_rr_rx_notif_nch(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_notification_nch *nn = msgb_l3(msg); + int payload_len = msgb_l3len(msg) - sizeof(*nn); + struct bitvec bv; + int rc; + + LOGP(DRR, LOGL_INFO, "NOTIFICATION/NCH\n"); + + bv = (struct bitvec) { + .data = nn->data, + .data_len = payload_len, + }; + + /* 0 | 1 <NLN(NCH) : bit (2) > */ + if (bitvec_get_bit_pos(&bv, bv.cur_bit++) == 1) { + /* NLN not used + nln = bitvec_get_uint(&bv, 2); + nln_present = true; + */ + bv.cur_bit += 2; + } + + /* < list of Group Call NCH information > */ + while (bitvec_get_bit_pos(&bv, bv.cur_bit++) == 1) { + rc = gsm48_rr_decode_group_call_info(ms, &bv, true); + if (rc < 0) + break; + } + + return 0; +} + +/* System information type 10 (9.1.50)*/ +static int gsm48_rr_rx_sysinfo_10(struct osmocom_ms *ms, struct msgb *msg) +{ + LOGP(DRR, LOGL_INFO, "SYSINFO 10\n"); + + /* Ignore content. */ + return -ENOTSUP; +} + +/* Provide uplink status to upper layer. */ +static int gsm48_rr_uplink_status(struct osmocom_ms *ms, uint32_t event) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; + + if (rr->group_state != GSM48_RR_GST_RECEIVE) + return -EINVAL; + + /* Send notification of uplink state to MM layer. */ + LOGP(DRR, LOGL_INFO, "Notify MM layer about uplink state.\n"); + nmsg = gsm48_mmevent_msgb_alloc(event); + if (!nmsg) + return -ENOMEM; + gsm48_mmevent_msg(rr->ms, nmsg); + + return 0; +} + +/* * random access */ @@ -1308,7 +2051,7 @@ && (!cs->selected || (cs->state != GSM322_C3_CAMPED_NORMALLY && cs->state != GSM322_C7_CAMPED_ANY_CELL))) { LOGP(DRR, LOGL_INFO, "Paging, but not camping, ignore.\n"); - return -EINVAL; + return -EINVAL; } /* ignore channel request while not camping on a cell */ @@ -2918,6 +3661,9 @@ LOGP(DSUM, LOGL_INFO, "Radio link lost signal\n"); + if (rr->group_state != GSM48_RR_GST_OFF) + return gsm48_rr_group_rel(ms, RR_REL_CAUSE_LOST_SIGNAL); + /* stop T3211 if running */ stop_rr_t3110(rr); @@ -3022,7 +3768,7 @@ gsm48_rr_tx_meas_rep(ms); /* establish */ - LOGP(DRR, LOGL_INFO, "establishing channel in dedicated mode\n"); + LOGP(DRR, LOGL_INFO, "establishing channel in dedicated/group mode\n"); if (rsl_dec_chan_nr(cd->chan_nr, &ch_type, &ch_subch, &ch_ts) != 0) { LOGP(DRR, LOGL_ERROR, @@ -3329,6 +4075,7 @@ struct gsm322_cellsel *cs = &ms->cellsel; uint8_t *mode; struct msgb *nmsg; + int msg_type; /* if MM has releases before confirm, we start release */ if (rr->state == GSM48_RR_ST_REL_PEND) { @@ -3352,8 +4099,11 @@ gsm48_rr_tx_cm_change(ms); /* send confirm to upper layer */ - nmsg = gsm48_rr_msgb_alloc( - (rr->rr_est_req) ? GSM48_RR_EST_CNF : GSM48_RR_EST_IND); + if (rr->rr_est_req) + msg_type = GSM48_RR_EST_CNF; + else + msg_type = GSM48_RR_EST_IND; + nmsg = gsm48_rr_msgb_alloc(msg_type); if (!nmsg) return -ENOMEM; return gsm48_rr_upmsg(ms, nmsg); @@ -3366,6 +4116,12 @@ struct msgb *nmsg; struct gsm48_rr_hdr *nrrh; + /* Handle on group channel. */ + if (rr->group_state == GSM48_RR_GST_TRANSMIT) { + LOGP(DRR, LOGL_INFO, "Returning to group receive mode, due to link release indication.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_NORMAL); + } + /* switch back to old channel, if modify/ho failed */ switch (rr->modify_state) { case GSM48_RR_MOD_ASSIGN: @@ -3435,6 +4191,9 @@ new_rr_state(rr, GSM48_RR_ST_REL_PEND); + /* When we receive a channel release, we are not just releasing the transmit mode. */ + rr->group_state = GSM48_RR_GST_OFF; + /* start T3110, so that two DISCs can be sent due to T200 timeout */ start_rr_t3110(rr, 1, 500000); @@ -4472,6 +5231,16 @@ return 0; } +/* send HANDOVER/UPLINK ACCESS burst (9.1.14) */ +static int gsm48_rr_tx_rand_acc_dedicated(struct osmocom_ms *ms, uint8_t ref, uint16_t offset, int8_t uic) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + + LOGP(DRR, LOGL_INFO, "send access bursts on DCCH (ref 0x%02x)\n", ref); + + return l1ctl_tx_rach_req(ms, rr->cd_now.chan_nr, 0x00, ref, 0, offset, uic); +} + /* send all queued messages down to layer 2 */ static int gsm48_rr_dequeue_down(struct osmocom_ms *ms) { @@ -4494,17 +5263,27 @@ return 0; } -/* channel is resumed in dedicated mode */ +/* Channel is resumed in dedicated mode or uplink is estabished. */ static int gsm48_rr_estab_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg) { struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; - LOGP(DRR, LOGL_INFO, "data link is resumed\n"); + if (rr->group_state == GSM48_RR_GST_TRANSMIT) { + LOGP(DRR, LOGL_INFO, "data link established on uplink\n"); - /* transmit queued frames during ho / ass transition */ - gsm48_rr_dequeue_down(ms); + /* Confirm uplink access. */ + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_UPLINK_CNF); + if (nmsg) + gsm48_rr_upmsg(ms, nmsg); + } else { + LOGP(DRR, LOGL_INFO, "data link is resumed\n"); - rr->modify_state = GSM48_RR_MOD_NONE; + /* transmit queued frames during ho / ass transition */ + gsm48_rr_dequeue_down(ms); + + rr->modify_state = GSM48_RR_MOD_NONE; + } return 0; } @@ -4594,6 +5373,13 @@ struct gsm48_rr_hdr *nrrh; uint16_t acc_class; + /* Reject during group call. */ + if (rr->group_state != GSM48_RR_GST_OFF) { + LOGP(DRR, LOGL_INFO, "We have a group call, rejecting!\n"); + cause = RR_REL_CAUSE_TRY_LATER; + goto reject; + } + /* 3.3.1.1.3.2 */ if (osmo_timer_pending(&rr->t3122)) { if (rrh->cause != RR_EST_CAUSE_EMERGENCY) { @@ -4681,10 +5467,225 @@ memcpy(msgb_put(rr->rr_est_msg, msgb_l3len(msg)), msgb_l3(msg), msgb_l3len(msg)); + if (rr->group_state == GSM48_RR_GST_RECEIVE) { + /* Release group receive mode. */ + l1ctl_tx_dm_rel_req(rr->ms); + rr->ms->meas.rl_fail = 0; + l1ctl_tx_reset_req(rr->ms, L1CTL_RES_T_SCHED); + } + /* request channel */ return gsm48_rr_chan_req(ms, rrh->cause, 0, 0); } +/* 3.3.3.2 Request for group receive mode. */ +static int gsm48_rr_group_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm322_cellsel *cs = &ms->cellsel; + struct gsm48_sysinfo *s = &cs->sel_si; + struct gsm48_rr_hdr *rrh = (struct gsm48_rr_hdr *) msg->data; + uint8_t cause; + struct msgb *nmsg; + struct gsm48_rr_hdr *nrrh; + struct gsm48_rr_cd cd; + uint8_t ch_type, ch_subch, ch_ts; + uint16_t ma[64]; + uint8_t ma_len; + int rc; + + /* if state is not idle */ + if (rr->state != GSM48_RR_ST_IDLE || rr->group_state != GSM48_RR_GST_OFF) { + LOGP(DRR, LOGL_INFO, "We are not IDLE yet, rejecting!\n"); + cause = RR_REL_CAUSE_TRY_LATER; + reject: + LOGP(DSUM, LOGL_INFO, "Joining group call channel not possible\n"); + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_GROUP_REL_IND); + if (!nmsg) + return -ENOMEM; + nrrh = (struct gsm48_rr_hdr *)nmsg->data; + nrrh->cause = cause; + return gsm48_rr_upmsg(ms, nmsg); + } + + /* cell selected */ + if (!cs->selected) { + LOGP(DRR, LOGL_INFO, "No cell selected, rejecting!\n"); + cause = RR_REL_CAUSE_TRY_LATER; + goto reject; + } + + /* check if camping */ + if (cs->state != GSM322_C3_CAMPED_NORMALLY + && cs->state != GSM322_C7_CAMPED_ANY_CELL) { + LOGP(DRR, LOGL_INFO, "Not camping, rejecting! " + "(cs->state = %d)\n", cs->state); + cause = RR_REL_CAUSE_TRY_LATER; + goto reject; + } + + /* get channel description */ + memset(&cd, 0, sizeof(cd)); + cd.chan_nr = rrh->ch_desc.chan_nr; + if (rsl_dec_chan_nr(cd.chan_nr, &ch_type, &ch_subch, &ch_ts) != 0) { + LOGP(DRR, LOGL_ERROR, + "%s(): rsl_dec_chan_nr(chan_nr=0x%02x) failed\n", + __func__, cd.chan_nr); + cause = GSM48_RR_CAUSE_CHAN_MODE_UNACCT; + goto reject; + } + if (rrh->ch_desc.h0.h) { + LOGP(DRR, LOGL_ERROR, "HOPPING NOT SUPPORTED, PLEASE FIX!\n"); + cd.h = 1; + gsm48_decode_chan_h1(&rrh->ch_desc, &cd.tsc, &cd.maio, + &cd.hsn); + LOGP(DRR, LOGL_INFO, " (chan_nr 0x%02x MAIO %u HSN %u TS %u SS %u TSC %u)\n", + rrh->ch_desc.chan_nr, cd.maio, cd.hsn, ch_ts, ch_subch, cd.tsc); + } else { + cd.h = 0; + gsm48_decode_chan_h0(&rrh->ch_desc, &cd.tsc, &cd.arfcn); + if (gsm_refer_pcs(cs->arfcn, s)) + cd.arfcn |= ARFCN_PCS; + LOGP(DRR, LOGL_INFO, " (chan_nr 0x%02x ARFCN %s TS %u SS %u TSC %u)\n", + rrh->ch_desc.chan_nr, gsm_print_arfcn(cd.arfcn), ch_ts, ch_subch, cd.tsc); + } + if (gsm48_rr_render_ma(ms, &rr->cd_group, ma, &ma_len)) { + cause = GSM48_RR_CAUSE_CHAN_MODE_UNACCT; + goto reject; + } + + /* Turn off transmitter. */ + cd.tch_flags |= L1CTL_TCH_FLAG_RXONLY; + + /* Set mode to Speech V1. FIXME: Add AMR support. */ + cd.mode = GSM48_CMODE_SPEECH_V1; + + /* Set current channel and also store as 'cd_group', used when leaving dedicated mode. */ + memcpy(&rr->cd_now, &cd, sizeof(rr->cd_now)); + memcpy(&rr->cd_group, &cd, sizeof(rr->cd_group)); + + /* tell cell selection process to leave idle mode + * NOTE: this must be sent unbuffered, because the state may not + * change until idle mode is left + */ + nmsg = gsm322_msgb_alloc(GSM322_EVENT_LEAVE_IDLE); + if (!nmsg) + return -ENOMEM; + rc = gsm322_c_event(ms, nmsg); + msgb_free(nmsg); + if (rc) { + LOGP(DRR, LOGL_INFO, "Failed to leave IDLE mode.\n"); + cause = GSM48_RR_CAUSE_CHAN_MODE_UNACCT; + goto reject; + } + + /* Initial uplink state. */ + rr->uplink_free = false; + + /* Set group state to receive mode. */ + rr->group_state = GSM48_RR_GST_RECEIVE; + + /* Wait until synced to the CCCH ... */ + return 0; +} +/* ... Continue after synced to the CCCH. */ +static int gsm48_rr_group_req_continue(struct osmocom_ms *ms) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + uint16_t ma[64]; + uint8_t ma_len; + struct msgb *nmsg; + + /* get hopping sequence, if required */ + gsm48_rr_render_ma(ms, &rr->cd_group, ma, &ma_len); + /* activate channel */ + gsm48_rr_activate_channel(ms, &rr->cd_group, ma, ma_len); + + /* Confirm group call channel. */ + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_GROUP_CNF); + if (!nmsg) + return -ENOMEM; + return gsm48_rr_upmsg(ms, nmsg); +} + +/* After "loss of signal"/release in group transmit or receive mode, return IDLE and release towards MM. */ +static int gsm48_rr_group_rel(struct osmocom_ms *ms, int cause) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; + struct gsm48_rr_hdr *nrrh; + uint8_t *mode; + + /* Stop group receive and transmit timers. */ + stop_rr_t_ul_free(rr); + stop_rr_t3128(rr); + stop_rr_t3130(rr); + + if (rr->state == GSM48_RR_ST_DEDICATED || rr->state == GSM48_RR_ST_REL_PEND) { + struct msgb *nmsg; + + LOGP(DRR, LOGL_INFO, "Channel lost, send (local) release to layer 2.\n"); + + /* Go into group receive mode, so that the channel gets released on LAPD release confirm. */ + rr->group_state = GSM48_RR_GST_RECEIVE; + if (rr->state != GSM48_RR_ST_REL_PEND) + new_rr_state(rr, GSM48_RR_ST_REL_PEND); + + /* release message */ + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + mode = msgb_put(nmsg, 2); + mode[0] = RSL_IE_RELEASE_MODE; + mode[1] = RSL_REL_LOCAL_END; + gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0); + + /* release SAPI 3 link, if exits */ + gsm48_release_sapi3_link(ms); + + /* Wait for LAPD to confirm. Then return idle. */ + return 0; + } + + /* Go back to IDLE mode. */ + rr->group_state = GSM48_RR_GST_OFF; + new_rr_state(rr, GSM48_RR_ST_IDLE); + + /* Indicate release to MM. */ + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_GROUP_REL_IND); + if (!nmsg) + return -ENOMEM; + nrrh = (struct gsm48_rr_hdr *)nmsg->data; + nrrh->cause = cause; + return gsm48_rr_upmsg(ms, nmsg); +} + +/* Release group channel, return to IDLE. */ +static int gsm48_rr_group_rel_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + + /* Only in group receive/transmit mode. */ + if (rr->group_state == GSM48_RR_GST_OFF) + return 0; + + /* Stop group receive and transmit timers. */ + stop_rr_t_ul_free(rr); + stop_rr_t3128(rr); + stop_rr_t3130(rr); + + /* Unset group state. Wait, if release is pending. */ + rr->group_state = GSM48_RR_GST_OFF; + if (rr->state != GSM48_RR_ST_IDLE) { + LOGP(DRR, LOGL_INFO, "Cannot release group channel yet, wait to return to IDLE state.\n"); + return 0; + } + + LOGP(DRR, LOGL_INFO, "Release Group channel.\n"); + new_rr_state(rr, GSM48_RR_ST_IDLE); + return 0; +} + /* 3.4.2 transfer data in dedicated mode */ static int gsm48_rr_data_req(struct osmocom_ms *ms, struct msgb *msg) { @@ -4770,6 +5771,9 @@ case GSM48_MT_RR_CHAN_REL: rc = gsm48_rr_rx_chan_rel(ms, msg); break; + case GSM48_MT_RR_UPLINK_RELEASE: + rc = gsm48_rr_rx_uplink_release(ms, msg); + break; case GSM48_MT_RR_APP_INFO: LOGP(DRR, LOGL_NOTICE, "APP INFO not supported!\n"); break; @@ -4849,6 +5853,10 @@ return gsm48_rr_rx_imm_ass_ext(ms, msg); case GSM48_MT_RR_IMM_ASS_REJ: return gsm48_rr_rx_imm_ass_rej(ms, msg); + + case GSM48_MT_RR_NOTIF_NCH: + return gsm48_rr_rx_notif_nch(ms, msg); + default: #if 0 LOGP(DRR, LOGL_NOTICE, "CCCH message type 0x%02x unknown.\n", @@ -4858,28 +5866,70 @@ } } +#define N201_Bter_SACCH 21 +#define N201_Bter_SDCCH_FACCH 23 +#define N201_B4 19 + /* receive ACCH at RR layer */ static int gsm48_rr_rx_acch(struct osmocom_ms *ms, struct msgb *msg) { - struct gsm48_rrlayer *rr = &ms->rrlayer; - struct gsm_settings *set = &ms->settings; - struct abis_rsl_rll_hdr *rllh = msgb_l2(msg); - struct gsm48_system_information_type_header *sih = msgb_l3(msg); + struct gsm48_system_information_type_header *sih; + struct gsm48_hdr_sh *sgh; + struct gsm48_hdr *gh; + /* Bter frame (SACCH or SDCCH/FACCH) */ + if (msgb_l3len(msg) == N201_Bter_SACCH || msgb_l3len(msg) == N201_Bter_SDCCH_FACCH) { + sgh = msgb_l3(msg); + if (sgh->rr_short_pd != GSM48_PDISC_SH_RR) { + LOGP(DRR, LOGL_NOTICE, "Short header message is not an RR message.\n"); + return -EINVAL; + } + switch (sgh->msg_type) { + case GSM48_MT_RR_SH_UL_FREE: + return gsm48_rr_rx_uplink_free(ms, msg); + case GSM48_MT_RR_SH_FACCH: + return gsm48_rr_rx_notif_facch(ms, msg); + case GSM48_MT_RR_SH_SI10: + return gsm48_rr_rx_sysinfo_10(ms, msg); + default: + LOGP(DRR, LOGL_NOTICE, "Short header message type 0x%02x unsupported.\n", sgh->msg_type); + return -EINVAL; + } + } + /* B4 frame (SACCH) */ + if ((msg->cb[0] & 0x40) && msgb_l3len(msg) == N201_B4) { + sih = msgb_l3(msg); + switch (sih->system_information) { + case GSM48_MT_RR_SYSINFO_5: + return gsm48_rr_rx_sysinfo5(ms, msg); + case GSM48_MT_RR_SYSINFO_5bis: + return gsm48_rr_rx_sysinfo5bis(ms, msg); + case GSM48_MT_RR_SYSINFO_5ter: + return gsm48_rr_rx_sysinfo5ter(ms, msg); + case GSM48_MT_RR_SYSINFO_6: + return gsm48_rr_rx_sysinfo6(ms, msg); + default: + LOGP(DRR, LOGL_NOTICE, "ACCH message type 0x%02x unknown.\n", sih->system_information); + return -EINVAL; + } + } - switch (sih->system_information) { - case GSM48_MT_RR_SYSINFO_5: - return gsm48_rr_rx_sysinfo5(ms, msg); - case GSM48_MT_RR_SYSINFO_5bis: - return gsm48_rr_rx_sysinfo5bis(ms, msg); - case GSM48_MT_RR_SYSINFO_5ter: - return gsm48_rr_rx_sysinfo5ter(ms, msg); - case GSM48_MT_RR_SYSINFO_6: - return gsm48_rr_rx_sysinfo6(ms, msg); + /* B frame (UI frame on VGCS) */ + if (msgb_l3len(msg) < sizeof(*gh)) { + LOGP(DRR, LOGL_NOTICE, "ACCH message too short.\n"); + return -EINVAL; + } + gh = msgb_l3(msg); + switch (gh->msg_type) { + case GSM48_MT_RR_VGCS_UPL_GRANT: + return gsm48_rr_rx_vgcs_uplink_grant(ms, msg); + case GSM48_MT_RR_UPLINK_BUSY: + return gsm48_rr_rx_uplink_busy(ms, msg); + case GSM48_MT_RR_CHAN_REL: + return gsm48_rr_rx_chan_rel_ui(ms, msg); default: - LOGP(DRR, LOGL_NOTICE, "ACCH message type 0x%02x unknown.\n", - sih->system_information); + LOGP(DRR, LOGL_NOTICE, "ACCH message type 0x%02x unknown.\n", gh->msg_type); return -EINVAL; } } @@ -4936,6 +5986,10 @@ LOGP(DCS, LOGL_INFO, "Channel provides data.\n"); cs->ccch_state = GSM322_CCCH_ST_DATA; + /* in group receive mode */ + if (ms->rrlayer.group_state == GSM48_RR_GST_RECEIVE) + return gsm48_rr_group_req_continue(ms); + /* in dedicated mode */ if (ms->rrlayer.state == GSM48_RR_ST_CONN_PEND) return gsm48_rr_tx_rand_acc(ms, NULL); @@ -5029,6 +6083,12 @@ uint16_t ma[64]; uint8_t ma_len; + /* Handle on group channel. */ + if (rr->group_state == GSM48_RR_GST_TRANSMIT) { + LOGP(DRR, LOGL_INFO, "Returning to group receive mode, due to link release confirm.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_NORMAL); + } + /* switch back to old channel, if modify/ho failed */ switch (rr->modify_state) { case GSM48_RR_MOD_ASSIGN: @@ -5075,7 +6135,11 @@ stop_rr_t3110(rr); /* send release indication */ - nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND); + if (rr->group_state == GSM48_RR_GST_RECEIVE) { + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_GROUP_REL_IND); + rr->group_state = GSM48_RR_GST_OFF; + } else + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_REL_IND); if (!nmsg) return -ENOMEM; nrrh = (struct gsm48_rr_hdr *)nmsg->data; @@ -5123,6 +6187,12 @@ if (rr->modify_state) return 0; + /* Handle on group channel. */ + if ((link_id & 7) == 0 && rr->group_state == GSM48_RR_GST_TRANSMIT) { + LOGP(DRR, LOGL_INFO, "Returning to group receive mode, due to link failure.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_LINK_FAILURE); + } + /* send abort ind to upper layer */ nmsg = gsm48_rr_msgb_alloc(GSM48_RR_ABORT_IND); if (!nmsg) @@ -5145,6 +6215,202 @@ return 0; } +/* Request uplink in group receive mode. */ +static int gsm48_rr_uplink_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; + struct gsm48_rr_hdr *nrrh; + + /* Only in group receive mode */ + if (rr->state != GSM48_RR_ST_IDLE || rr->group_state != GSM48_RR_GST_RECEIVE) { + LOGP(DRR, LOGL_INFO, "We are not in group receive mode yet, rejecting!\n"); + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_UPLINK_REL_IND); + if (!nmsg) + return -ENOMEM; + nrrh = (struct gsm48_rr_hdr *)nmsg->data; + nrrh->cause = RR_REL_CAUSE_TRY_LATER; + return gsm48_rr_upmsg(ms, nmsg); + } + + LOGP(DRR, LOGL_INFO, "Changing from group receive mode to group transmit mode.\n"); + + /* Enter uplink access procedure. */ + new_rr_state(rr, GSM48_RR_ST_CONN_PEND); + + /* Set group state to transmit mode. */ + rr->group_state = GSM48_RR_GST_TRANSMIT; + + /* Uplink investigation procedure (3.3.1.2.1.1) */ + if (!rr->uplink_free) { + start_rr_t3128(rr, GSM_T3128_MS); + return 0; + } + + rr->uplink_tries = 3; + return gsm48_rr_uplink_access(ms, NULL); +} + +/* Start uplink access procedure. (3.3.1.2.1.2) */ +static int gsm48_rr_uplink_access(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + + /* store frame number */ + if (msg) { + struct abis_rsl_cchan_hdr *ch = msgb_l2(msg); + struct gsm48_req_ref *ref = + (struct gsm48_req_ref *) (ch->data + 1); + + if (msgb_l2len(msg) < sizeof(*ch) + sizeof(*ref)) { + LOGP(DRR, LOGL_ERROR, "CHAN_CNF too slort\n"); + return -EINVAL; + } + + /* Store to history buffer. */ + /* shift history and store */ + memcpy(&(rr->cr_hist[4]), &(rr->cr_hist[3]), + sizeof(struct gsm48_cr_hist)); + memcpy(&(rr->cr_hist[3]), &(rr->cr_hist[2]), + sizeof(struct gsm48_cr_hist)); + memcpy(&(rr->cr_hist[2]), &(rr->cr_hist[1]), + sizeof(struct gsm48_cr_hist)); + memcpy(&(rr->cr_hist[1]), &(rr->cr_hist[0]), + sizeof(struct gsm48_cr_hist)); + rr->cr_hist[0].valid = 1; + rr->cr_hist[0].ref.ra = rr->cr_ra; + rr->cr_hist[0].ref.t1 = ref->t1; + rr->cr_hist[0].ref.t2 = ref->t2; + rr->cr_hist[0].ref.t3_low = ref->t3_low; + rr->cr_hist[0].ref.t3_high = ref->t3_high; + } + + if (!osmo_timer_pending(&rr->t3130)) { + uint8_t uplink_ref; + + /* Only try up to 3 times. */ + if (!rr->uplink_tries) { + LOGP(DRR, LOGL_NOTICE, "Abort uplink access, due uplink access timeout.\n"); + return gsm48_rr_uplink_access_abort(ms, RR_REL_CAUSE_LINK_FAILURE); + } + + LOGP(DRR, LOGL_INFO, "Trying to access uplink.\n"); + + rr->uplink_tries--; + + /* See Table 9.1.45.1 */ + uplink_ref = layer23_random(); + uplink_ref &= 0x1f; + uplink_ref |= 0xc0; + + /* store value, mask and history */ + rr->cr_ra = uplink_ref; + rr->cr_hist[4].valid = 0; + rr->cr_hist[3].valid = 0; + rr->cr_hist[2].valid = 0; + rr->cr_hist[1].valid = 0; + rr->cr_hist[0].valid = 0; + + /* Reset counter. */ + rr->uplink_counter = 0; + + /* Start T3130. */ + start_rr_t3130(rr, GSM_T3130_MS); + } + + /* Send random access bursts up to 5 times. */ + if (rr->uplink_counter < 5) { + int delay_ms; + + /* The first UPLINK ACCESS message shall be delayed between 0..20ms. + * Subsequent UPLINK ACCESS messages shall be delayed 100ms + 0..20ms. */ + delay_ms = (layer23_random() & 0xffff) / 3277; + if (rr->uplink_counter) + delay_ms += 100; + + gsm48_rr_tx_rand_acc_dedicated(ms, rr->cr_ra, delay_ms * 26 / 120, rr->uic); + rr->uplink_counter++; + } + + return 0; +} + +/* Whenever uplink access is released or failed for some reason. */ +static int gsm48_rr_uplink_access_abort(struct osmocom_ms *ms, uint8_t cause) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct msgb *nmsg; + struct gsm48_rr_hdr *nrrh; + + /* Stop group transmit mode timers. */ + stop_rr_t3128(rr); + stop_rr_t3130(rr); + + /* Turn off transmitter. */ + rr->cd_now.tch_flags |= L1CTL_TCH_FLAG_RXONLY; + gsm48_rr_set_mode(ms, rr->cd_now.chan_nr, rr->cd_now.mode, rr->cd_now.tch_flags); + + /* Only return IDLE without changing channel, because we are still in group transmit mode. */ + new_rr_state(rr, GSM48_RR_ST_IDLE); + + /* Set group state to receive mode. */ + rr->group_state = GSM48_RR_GST_RECEIVE; + + nmsg = gsm48_rr_msgb_alloc(GSM48_RR_UPLINK_REL_IND); + if (!nmsg) + return -ENOMEM; + nrrh = (struct gsm48_rr_hdr *)nmsg->data; + nrrh->cause = cause; + return gsm48_rr_upmsg(ms, nmsg); +} + +/* Leave uplink, also called when leaving group channel. */ +static int gsm48_rr_uplink_rel_req(struct osmocom_ms *ms, struct msgb *msg) +{ + struct gsm48_rrlayer *rr = &ms->rrlayer; + struct gsm_settings *set = &ms->settings; + struct msgb *nmsg; + uint8_t *mode; + + /* Only in group transmit mode */ + if (rr->group_state != GSM48_RR_GST_TRANSMIT) + return -EINVAL; + + /* Stop group transmit mode timers. */ + stop_rr_t3128(rr); + stop_rr_t3130(rr); + + /* Continue if in dedicated mode, so we release and wait for uplink to become free. */ + if (rr->state != GSM48_RR_ST_DEDICATED) + return 0; + + LOGP(DRR, LOGL_INFO, "Returning from group transmit to group receive mode.\n"); + + /* Leave uplink, wait for uplink beeing free, channel release or channel/link failure. */ + gsm48_rr_tx_uplink_release(ms, GSM48_RR_CAUSE_LEAVE_GROUP_CA); + + /* Go into release pending mode. */ + new_rr_state(rr, GSM48_RR_ST_REL_PEND); + + /* Special setting where we release locally. This means we wait for free uplink an then release. */ + if (set->uplink_release_local) { + LOGP(DRR, LOGL_INFO, "Release L2 locally as specified via VTY. Wait for UPLINK FREE.\n"); + return 0; + } + + /* Release dedicated mode. */ + /* disconnect the main signalling link */ + nmsg = gsm48_l3_msgb_alloc(); + if (!nmsg) + return -ENOMEM; + mode = msgb_put(nmsg, 2); + mode[0] = RSL_IE_RELEASE_MODE; + mode[1] = RSL_REL_NORMAL; + gsm48_send_rsl_nol3(ms, RSL_MT_REL_REQ, nmsg, 0); + + return 0; +} + static int gsm48_rr_estab_ind_sapi3(struct osmocom_ms *ms, struct msgb *msg) { struct gsm48_rrlayer *rr = &ms->rrlayer; @@ -5385,11 +6651,6 @@ {SBIT(GSM48_RR_ST_DEDICATED), RSL_MT_SUSP_CONF, gsm48_rr_susp_cnf_dedicated}, -#if 0 - {SBIT(GSM48_RR_ST_DEDICATED), - RSL_MT_CHAN_CNF, gsm48_rr_rand_acc_cnf_dedicated}, -#endif - {SBIT(GSM48_RR_ST_DEDICATED), RSL_MT_ERROR_IND, gsm48_rr_mdl_error_ind}, }; @@ -5486,11 +6747,24 @@ "%s\n", ms->name, rsl_msg_name(msg_type), gsm48_rr_state_names[rr->state]); - if (rr->state == GSM48_RR_ST_CONN_PEND - && msg_type == RSL_MT_CHAN_CONF) { - rc = gsm48_rr_tx_rand_acc(ms, msg); - msgb_free(msg); - return rc; + if (msg_type == RSL_MT_CHAN_CONF) { + /* Recevie confirm to get the FN when the access burst was transmitted on VGCS channel. */ + if (rr->state == GSM48_RR_ST_CONN_PEND && rr->group_state == GSM48_RR_GST_TRANSMIT) { + rc = gsm48_rr_uplink_access(ms, msg); + msgb_free(msg); + return rc; + } + /* Ignore subsequent access bursts in dedicated group transmit mode. */ + if (rr->state == GSM48_RR_ST_DEDICATED && rr->group_state == GSM48_RR_GST_TRANSMIT) { + msgb_free(msg); + return 0; + } + /* Recevie confirm to get the FN when the access burst was transmitted on CCCH. */ + if (rr->state == GSM48_RR_ST_CONN_PEND) { + rc = gsm48_rr_tx_rand_acc(ms, msg); + msgb_free(msg); + return rc; + } } LOGP(DRSL, LOGL_NOTICE, "RSLms message unhandled\n"); @@ -5542,6 +6816,20 @@ {SBIT(GSM48_RR_ST_CONN_PEND) | SBIT(GSM48_RR_ST_DEDICATED), /* 3.4.13.3 */ GSM48_RR_ABORT_REQ, gsm48_rr_abort_req}, + + /* NOTE: If not IDLE, it is rejected there. */ + {ALL_STATES, /* 3.3.3.2 */ + GSM48_RR_GROUP_REQ, gsm48_rr_group_req}, + + {ALL_STATES, + GSM48_RR_GROUP_REL_REQ, gsm48_rr_group_rel_req}, + + /* NOTE: If not IDLE, it is rejected there. */ + {ALL_STATES, /* 3.3.1.2 */ + GSM48_RR_UPLINK_REQ, gsm48_rr_uplink_req}, + + {ALL_STATES, /* 3.4.13.4 */ + GSM48_RR_UPLINK_REL_REQ, gsm48_rr_uplink_rel_req}, }; #define RRDOWNSLLEN \ @@ -5652,6 +6940,9 @@ rr->audio_mode = 0x00; } + /* List of notifications about ongoing ASCI calls */ + INIT_LLIST_HEAD(&rr->notif_list); + return 0; } @@ -5680,6 +6971,12 @@ stop_rr_t3122(rr); stop_rr_t3124(rr); stop_rr_t3126(rr); + stop_rr_t_ul_free(rr); + stop_rr_t3128(rr); + stop_rr_t3130(rr); + + /* Free pending list entries. */ + asci_notif_list_free(rr); return 0; } @@ -5723,54 +7020,6 @@ osmo_timer_schedule(&rr->t3124, sec, micro); } -/* send HANDOVER ACCESS burst (9.1.14) */ -static int gsm48_rr_tx_hando_access(struct osmocom_ms *ms) -{ - nmsg = msgb_alloc_headroom(20, 16, "HAND_ACCESS"); - if (!nmsg) - return -ENOMEM; - *msgb_put(nmsg, 1) = rr->hando_ref; - todo burst - return gsm48_send_rsl(ms, RSL_MT_RAND_ACC_REQ, nmsg, 0); -} - -/* send next channel request in dedicated state */ -static int gsm48_rr_rand_acc_cnf_dedicated(struct osmocom_ms *ms, struct msgb *msg) -{ - struct gsm48_rrlayer *rr = &ms->rrlayer; - struct msgb *nmsg; - int s; - - if (rr->modify_state != GSM48_RR_MOD_HANDO) { - LOGP(DRR, LOGL_NOTICE, "Random access confirm, but not in handover state.\n"); - return 0; - } - - /* send up to four handover access bursts */ - if (rr->hando_acc_left) { - rr->hando_acc_left--; - gsm48_rr_tx_hando_access(ms); - return; - } - - /* start timer for sending next HANDOVER ACCESS bursts afterwards */ - if (!osmo_timer_pending(&rr->t3124)) { - if (allocated channel is SDCCH) - start_rr_t3124(rr, GSM_T3124_675); - else - start_rr_t3124(rr, GSM_T3124_320); - } - if (!rr->n_chan_req) { - start_rr_t3126(rr, 5, 0); /* TODO improve! */ - return 0; - } - rr->n_chan_req--; - - /* wait for PHYSICAL INFORMATION message or T3124 timeout */ - return 0; - -} - #endif int gsm48_rr_tx_voice(struct osmocom_ms *ms, struct msgb *msg) @@ -5806,6 +7055,9 @@ struct gsm48_rrlayer *rr = &ms->rrlayer; uint8_t ch_type, ch_subch, ch_ts; + if (ms->settings.audio.io_handler != AUDIO_IOH_NONE) + return 0; + LOGP(DRR, LOGL_INFO, "setting audio mode to %d\n", mode); rr->audio_mode = mode; -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34491?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Ia55c182a1b4cde777a0e16dcfe0cd32e0f2e38eb Gerrit-Change-Number: 34491 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: ASCI: Add protocol type to trans_find_by_callref() function
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34493?usp=email
) Change subject: ASCI: Add protocol type to trans_find_by_callref() function ...................................................................... ASCI: Add protocol type to trans_find_by_callref() function This is required, because different protocols may share the same callref, but use different protocols. E.g. a voice group call can share the same callref with a voice broadcast call, but these calls are different transactions. Related: OS#5364 Change-Id: Ifea3a81aae3b4ae897851f867b13fa987c8cbe11 --- M src/host/layer23/include/osmocom/bb/mobile/transaction.h M src/host/layer23/src/mobile/gsm411_sms.c M src/host/layer23/src/mobile/gsm480_ss.c M src/host/layer23/src/mobile/gsm48_cc.c M src/host/layer23/src/mobile/transaction.c 5 files changed, 22 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/93/34493/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/transaction.h b/src/host/layer23/include/osmocom/bb/mobile/transaction.h index 8c06d5d..1c998cd 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/transaction.h +++ b/src/host/layer23/include/osmocom/bb/mobile/transaction.h @@ -62,7 +62,7 @@ struct gsm_trans *trans_find_by_id(struct osmocom_ms *ms, uint8_t proto, uint8_t trans_id); -struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms, +struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms, uint8_t protocol, uint32_t callref); struct gsm_trans *trans_alloc(struct osmocom_ms *ms, diff --git a/src/host/layer23/src/mobile/gsm411_sms.c b/src/host/layer23/src/mobile/gsm411_sms.c index 64d098c..a5454b7 100644 --- a/src/host/layer23/src/mobile/gsm411_sms.c +++ b/src/host/layer23/src/mobile/gsm411_sms.c @@ -914,7 +914,7 @@ struct gsm_trans *trans; int rc = 0; - trans = trans_find_by_callref(ms, mmh->ref); + trans = trans_find_by_callref(ms, GSM48_PDISC_SMS, mmh->ref); if (!trans) { LOGP(DLSMS, LOGL_INFO, " -> (new transaction sapi=%d)\n", sapi); trans = trans_alloc(ms, GSM48_PDISC_SMS, mmh->transaction_id, diff --git a/src/host/layer23/src/mobile/gsm480_ss.c b/src/host/layer23/src/mobile/gsm480_ss.c index 202e1e7..bf99667 100644 --- a/src/host/layer23/src/mobile/gsm480_ss.c +++ b/src/host/layer23/src/mobile/gsm480_ss.c @@ -1240,7 +1240,7 @@ struct gsm_trans *trans; int rc = 0; - trans = trans_find_by_callref(ms, mmh->ref); + trans = trans_find_by_callref(ms, GSM48_PDISC_NC_SS, mmh->ref); if (!trans) { LOGP(DSS, LOGL_INFO, " -> (new transaction)\n"); trans = trans_alloc(ms, GSM48_PDISC_NC_SS, mmh->transaction_id, diff --git a/src/host/layer23/src/mobile/gsm48_cc.c b/src/host/layer23/src/mobile/gsm48_cc.c index 43c93fc..190eb91 100644 --- a/src/host/layer23/src/mobile/gsm48_cc.c +++ b/src/host/layer23/src/mobile/gsm48_cc.c @@ -1937,7 +1937,7 @@ data->msg_type = msg_type; /* Find callref */ - trans = trans_find_by_callref(ms, data->callref); + trans = trans_find_by_callref(ms, GSM48_PDISC_CC, data->callref); if (!trans) { /* check for SETUP message */ @@ -2147,7 +2147,7 @@ struct gsm_trans *trans; int rc = 0; - trans = trans_find_by_callref(ms, mmh->ref); + trans = trans_find_by_callref(ms, GSM48_PDISC_CC, mmh->ref); if (!trans) { trans = trans_alloc(ms, GSM48_PDISC_CC, mmh->transaction_id, mmh->ref); diff --git a/src/host/layer23/src/mobile/transaction.c b/src/host/layer23/src/mobile/transaction.c index 2fb910a..712a8ee 100644 --- a/src/host/layer23/src/mobile/transaction.c +++ b/src/host/layer23/src/mobile/transaction.c @@ -44,13 +44,13 @@ return NULL; } -struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms, +struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms, uint8_t protocol, uint32_t callref) { struct gsm_trans *trans; llist_for_each_entry(trans, &ms->trans_list, entry) { - if (trans->callref == callref) + if (trans->protocol == protocol && trans->callref == callref) return trans; } return NULL; -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34493?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Ifea3a81aae3b4ae897851f867b13fa987c8cbe11 Gerrit-Change-Number: 34493 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: ASCI: Add UIC support to random access burst
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34482?usp=email
) Change subject: ASCI: Add UIC support to random access burst ...................................................................... ASCI: Add UIC support to random access burst A different identity code can be used on uplink access bursts on voice group channel. This is optional for the network, but mandatory for the MS side. If the network does not define a UIC, the BSIC is used instead. BSIC is used for RACH channel and handover. Related: OS#5364 Change-Id: I4039734676949aefa5be4b5298764b8ba7e1b8ed --- M include/l1ctl_proto.h M src/host/layer23/include/osmocom/bb/common/l1ctl.h M src/host/layer23/src/common/l1ctl.c M src/host/layer23/src/common/l1ctl_lapdm_glue.c M src/host/layer23/src/modem/grr.c M src/target/firmware/include/layer1/prim.h M src/target/firmware/include/layer1/sync.h M src/target/firmware/layer1/l23_api.c M src/target/firmware/layer1/prim_rach.c 9 files changed, 35 insertions(+), 13 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/82/34482/1 diff --git a/include/l1ctl_proto.h b/include/l1ctl_proto.h index ab37746..2f7e8c8 100644 --- a/include/l1ctl_proto.h +++ b/include/l1ctl_proto.h @@ -229,6 +229,7 @@ uint8_t ra; uint8_t combined; uint16_t offset; + int8_t uic; } __attribute__((packed)); diff --git a/src/host/layer23/include/osmocom/bb/common/l1ctl.h b/src/host/layer23/include/osmocom/bb/common/l1ctl.h index fbfb766..f8c79db 100644 --- a/src/host/layer23/include/osmocom/bb/common/l1ctl.h +++ b/src/host/layer23/include/osmocom/bb/common/l1ctl.h @@ -23,7 +23,7 @@ /* Transmit L1CTL_RACH_REQ */ int l1ctl_tx_rach_req(struct osmocom_ms *ms, uint8_t chan_nr, uint8_t link_id, - uint8_t ra, uint16_t offset, uint8_t combined); + uint8_t ra, uint16_t offset, uint8_t combined, int8_t uic); /* Transmit L1CTL_DM_EST_REQ */ int l1ctl_tx_dm_est_req_h0(struct osmocom_ms *ms, uint16_t band_arfcn, uint8_t chan_nr, uint8_t tsc, diff --git a/src/host/layer23/src/common/l1ctl.c b/src/host/layer23/src/common/l1ctl.c index 8a66af8..65f78cf 100644 --- a/src/host/layer23/src/common/l1ctl.c +++ b/src/host/layer23/src/common/l1ctl.c @@ -513,7 +513,7 @@ /* Transmit L1CTL_RACH_REQ */ int l1ctl_tx_rach_req(struct osmocom_ms *ms, uint8_t chan_nr, uint8_t link_id, - uint8_t ra, uint16_t offset, uint8_t combined) + uint8_t ra, uint16_t offset, uint8_t combined, int8_t uic) { struct msgb *msg; struct l1ctl_info_ul *ul; @@ -523,7 +523,7 @@ if (!msg) return -1; - DEBUGP(DL1C, "RACH Req. offset=%d combined=%d\n", offset, combined); + DEBUGP(DL1C, "RACH Req. offset=%d combined=%d uic=%d\n", offset, combined, uic); ul = (struct l1ctl_info_ul *) msgb_put(msg, sizeof(*ul)); ul->chan_nr = chan_nr; ul->link_id = link_id; @@ -531,6 +531,7 @@ req->ra = ra; req->offset = htons(offset); req->combined = combined; + req->uic = uic; return osmo_send_l1(ms, msg); } diff --git a/src/host/layer23/src/common/l1ctl_lapdm_glue.c b/src/host/layer23/src/common/l1ctl_lapdm_glue.c index 601bed6..c28d63d 100644 --- a/src/host/layer23/src/common/l1ctl_lapdm_glue.c +++ b/src/host/layer23/src/common/l1ctl_lapdm_glue.c @@ -52,7 +52,8 @@ RSL_CHAN_RACH, 0x00, pp->u.rach_req.ra, pp->u.rach_req.offset, - pp->u.rach_req.is_combined_ccch); + pp->u.rach_req.is_combined_ccch, + -1); break; default: rc = -EINVAL; diff --git a/src/host/layer23/src/modem/grr.c b/src/host/layer23/src/modem/grr.c index 24411f7..3892af4 100644 --- a/src/host/layer23/src/modem/grr.c +++ b/src/host/layer23/src/modem/grr.c @@ -558,7 +558,7 @@ LOGPFSML(fi, LOGL_INFO, "Sending CHANNEL REQUEST (0x%02x)\n", rr->cr_ra); l1ctl_tx_rach_req(ms, RSL_CHAN_RACH, 0x00, rr->cr_ra, 0, - ms->cellsel.ccch_mode == CCCH_MODE_COMBINED); + ms->cellsel.ccch_mode == CCCH_MODE_COMBINED, -1); rr->state = GSM48_RR_ST_CONN_PEND; break; diff --git a/src/target/firmware/include/layer1/prim.h b/src/target/firmware/include/layer1/prim.h index 30c51ae..6d1d0b2 100644 --- a/src/target/firmware/include/layer1/prim.h +++ b/src/target/firmware/include/layer1/prim.h @@ -20,7 +20,7 @@ void l1s_fbsb_req(uint8_t base_fn, struct l1ctl_fbsb_req *req); void l1a_freq_req(uint32_t fn_sched); -void l1a_rach_req(uint16_t offset, uint8_t combined, uint8_t ra); +void l1a_rach_req(uint16_t offset, uint8_t combined, uint8_t ra, int8_t uic); /* Primitives raw scheduling sets */ extern const struct tdma_sched_item nb_sched_set[]; diff --git a/src/target/firmware/include/layer1/sync.h b/src/target/firmware/include/layer1/sync.h index ff56354..7b049c4 100644 --- a/src/target/firmware/include/layer1/sync.h +++ b/src/target/firmware/include/layer1/sync.h @@ -117,6 +117,7 @@ struct { uint8_t ra; + int8_t uic; } rach; struct { diff --git a/src/target/firmware/layer1/l23_api.c b/src/target/firmware/layer1/l23_api.c index 68bb2c0..ccbdf1a 100644 --- a/src/target/firmware/layer1/l23_api.c +++ b/src/target/firmware/layer1/l23_api.c @@ -386,11 +386,10 @@ struct l1ctl_info_ul *ul = (struct l1ctl_info_ul *) l1h->data; struct l1ctl_rach_req *rach_req = (struct l1ctl_rach_req *) ul->payload; - printd("L1CTL_RACH_REQ (ra=0x%02x, offset=%d, combined=%d)\n", - rach_req->ra, ntohs(rach_req->offset), rach_req->combined); + printd("L1CTL_RACH_REQ (ra=0x%02x, offset=%d, combined=%d, uic=%d)\n", + rach_req->ra, ntohs(rach_req->offset), rach_req->combined, rach_req->uic); - l1a_rach_req(ntohs(rach_req->offset), rach_req->combined, - rach_req->ra); + l1a_rach_req(ntohs(rach_req->offset), rach_req->combined, rach_req->ra, rach_req->uic); } /* receive a L1CTL_DATA_REQ from L23 */ diff --git a/src/target/firmware/layer1/prim_rach.c b/src/target/firmware/layer1/prim_rach.c index c342142..07058f0 100644 --- a/src/target/firmware/layer1/prim_rach.c +++ b/src/target/firmware/layer1/prim_rach.c @@ -61,8 +61,11 @@ putchart('T'); l1s_tx_apc_helper(l1s.serving_cell.arfcn); - - data[0] = l1s.serving_cell.bsic << 2; + + if (l1s.rach.uic < 0) + data[0] = l1s.serving_cell.bsic << 2; + else + data[0] = l1s.rach.uic << 2; data[1] = l1s.rach.ra; info_ptr = &dsp_api.ndb->d_rach; @@ -128,7 +131,7 @@ 45, 46}; /* schedule access burst */ -void l1a_rach_req(uint16_t offset, uint8_t combined, uint8_t ra) +void l1a_rach_req(uint16_t offset, uint8_t combined, uint8_t ra, int8_t uic) { uint32_t fn_sched; unsigned long flags; @@ -158,6 +161,7 @@ } else fn_sched = l1s.current_time.fn + offset; l1s.rach.ra = ra; + l1s.rach.uic = uic; fn_sched %= 2715648; sched_gsmtime(rach_sched_set_ul, fn_sched, 0); local_irq_restore(flags); -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34482?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I4039734676949aefa5be4b5298764b8ba7e1b8ed Gerrit-Change-Number: 34482 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: ASCI: Add support flags to mobile (and VTY) for VGCS/VBS
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34483?usp=email
) Change subject: ASCI: Add support flags to mobile (and VTY) for VGCS/VBS ...................................................................... ASCI: Add support flags to mobile (and VTY) for VGCS/VBS These support flags can be enabled or disabled and are sent in the class mark IE. Also they allow or disallow making VGCS/VBS calls. Related: OS#5364 Change-Id: Ia23eb190e533660cce4ba4c856a83b5f3d534202 --- M src/host/layer23/include/osmocom/bb/common/settings.h M src/host/layer23/src/common/support.c M src/host/layer23/src/mobile/vty_interface.c 3 files changed, 34 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/83/34483/1 diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h index 56475e3..52b485d 100644 --- a/src/host/layer23/include/osmocom/bb/common/settings.h +++ b/src/host/layer23/include/osmocom/bb/common/settings.h @@ -161,6 +161,10 @@ uint8_t ch_cap; /* channel capability */ int8_t min_rxlev_dbm; /* min dBm to access */ + /* support for ASCI */ + uint8_t vgcs; /* support of VGCS */ + uint8_t vbs; /* support of VBS */ + /* radio */ uint16_t dsc_max; uint8_t force_rekey; diff --git a/src/host/layer23/src/common/support.c b/src/host/layer23/src/common/support.c index e82d49f..37f642b 100644 --- a/src/host/layer23/src/common/support.c +++ b/src/host/layer23/src/common/support.c @@ -34,9 +34,9 @@ /* revision level */ sup->rev_lev = 1; /* phase 2 mobile station */ /* support of VGCS */ - sup->vgcs = 0; /* no */ + sup->vgcs = 1; /* yes */ /* support of VBS */ - sup->vbs = 0; /* no */ + sup->vbs = 1; /* yes */ /* support of SMS */ sup->sms_ptp = 1; /* no */ /* screening indicator */ diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c index 9b9ba95..feb5f84 100644 --- a/src/host/layer23/src/mobile/vty_interface.c +++ b/src/host/layer23/src/mobile/vty_interface.c @@ -1075,6 +1075,8 @@ if (!l23_vty_hide_default || set->any_timeout != MOB_C7_DEFLT_ANY_TIMEOUT) vty_out(vty, " c7-any-timeout %d%s", set->any_timeout, VTY_NEWLINE); + SUP_WRITE(vgcs, "vgcs"); + SUP_WRITE(vbs, "vbs"); vty_out(vty, " audio%s", VTY_NEWLINE); vty_out(vty, " io-handler %s%s", @@ -2052,6 +2054,15 @@ return CMD_SUCCESS; } +SUP_EN(cfg_ms_sup_vbs, cfg_ms_sup_vbs_cmd, vbs, "vbs", + "Voice Broadcast Service (VBS)", 0); +SUP_DI(cfg_ms_sup_no_vbs, cfg_ms_sup_no_vbs_cmd, vbs, + "vbs", "Voice Broadcast Service (VBS)", 0); +SUP_EN(cfg_ms_sup_vgcs, cfg_ms_sup_vgcs_cmd, vgcs, "vgcs", + "Voice Group Call Service (VGCS)", 0); +SUP_DI(cfg_ms_sup_no_vgcs, cfg_ms_sup_no_vgcs_cmd, vgcs, + "vgcs", "Voice Group Call Service (VBS)", 0); + /* per audio config */ DEFUN(cfg_ms_audio, cfg_ms_audio_cmd, "audio", "Configure audio settings") @@ -2380,6 +2391,10 @@ install_element(SUPPORT_NODE, &cfg_ms_sup_dsc_max_cmd); install_element(SUPPORT_NODE, &cfg_ms_sup_skip_max_per_band_cmd); install_element(SUPPORT_NODE, &cfg_ms_sup_no_skip_max_per_band_cmd); + install_element(SUPPORT_NODE, &cfg_ms_sup_vbs_cmd); + install_element(SUPPORT_NODE, &cfg_ms_sup_no_vbs_cmd); + install_element(SUPPORT_NODE, &cfg_ms_sup_vgcs_cmd); + install_element(SUPPORT_NODE, &cfg_ms_sup_no_vgcs_cmd); install_element(MS_NODE, &cfg_ms_script_load_run_cmd); install_element(MS_NODE, &cfg_ms_no_script_load_run_cmd); -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34483?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Ia23eb190e533660cce4ba4c856a83b5f3d534202 Gerrit-Change-Number: 34483 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[M] Change in osmocom-bb[master]: Refactoring encoding of mobile identity at mobile application
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34484?usp=email
) Change subject: Refactoring encoding of mobile identity at mobile application ...................................................................... Refactoring encoding of mobile identity at mobile application Deprecated functions gsm48_generate_mid_from_*() are replaced by osmo_mobile_identity_encode_msgb(). Clean up code. Change-Id: I9ff429bd50d718530fdad64a276053a35c8928f2 --- M src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h M src/host/layer23/src/mobile/gsm48_mm.c M src/host/layer23/src/mobile/gsm48_rr.c 3 files changed, 75 insertions(+), 61 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/84/34484/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h index 3ece82e..4d8a353 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h @@ -240,6 +240,7 @@ int state; }; +int gsm48_encode_mi(struct osmocom_ms *ms, struct msgb *msg, bool tlv, uint8_t mi_type, bool emergency_imsi); uint8_t gsm48_current_pwr_lev(struct gsm_settings *set, uint16_t arfcn); int gsm48_mm_init(struct osmocom_ms *ms); int gsm48_mm_exit(struct osmocom_ms *ms); diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c index 70a35f8..14a2721 100644 --- a/src/host/layer23/src/mobile/gsm48_mm.c +++ b/src/host/layer23/src/mobile/gsm48_mm.c @@ -272,41 +272,59 @@ return length; } -/* encode 'mobile identity' */ -int gsm48_encode_mi(uint8_t *buf, struct msgb *msg, struct osmocom_ms *ms, - uint8_t mi_type) +/* Encode and append 'mobile identity' of given type to message, based on current settings. */ +int gsm48_encode_mi(struct osmocom_ms *ms, struct msgb *msg, bool tlv, uint8_t mi_type, bool emergency_imsi) { struct gsm_subscriber *subscr = &ms->subscr; struct gsm_settings *set = &ms->settings; - uint8_t *ie; + struct osmo_mobile_identity mi = { }; + int rc; + uint8_t *l; - switch(mi_type) { + /* Copy MI values according to their types. */ + switch (mi_type) { case GSM_MI_TYPE_TMSI: - gsm48_generate_mid_from_tmsi(buf, subscr->tmsi); + mi.tmsi = subscr->tmsi; break; case GSM_MI_TYPE_IMSI: - gsm48_generate_mid_from_imsi(buf, subscr->imsi); + if (emergency_imsi) + OSMO_STRLCPY_ARRAY(mi.imsi, set->emergency_imsi); + else + OSMO_STRLCPY_ARRAY(mi.imsi, subscr->imsi); break; case GSM_MI_TYPE_IMEI: - gsm48_generate_mid_from_imsi(buf, set->imei); + OSMO_STRLCPY_ARRAY(mi.imei, set->imei); break; case GSM_MI_TYPE_IMEISV: - gsm48_generate_mid_from_imsi(buf, set->imeisv); + OSMO_STRLCPY_ARRAY(mi.imeisv, set->imeisv); + break; + } + + /* Append IE type. */ + if (tlv) + msgb_put_u8(msg, GSM48_IE_MOBILE_ID); + + /* Generate MI or 'NONE', if not available. */ + switch (mi_type) { + case GSM_MI_TYPE_TMSI: + case GSM_MI_TYPE_IMSI: + case GSM_MI_TYPE_IMEI: + case GSM_MI_TYPE_IMEISV: + mi.type = mi_type; + l = msgb_put(msg, 1); + rc = osmo_mobile_identity_encode_msgb(msg, &mi, true); + if (rc < 0) { + LOGP(DMM, LOGL_ERROR, "Failed to encode mobile identity type %d. Please fix!\n", mi_type); + *l = 1; + msgb_put_u8(msg, 0xf0 | GSM_MI_TYPE_NONE); + break; + } + *l = rc; break; case GSM_MI_TYPE_NONE: default: - buf[0] = GSM48_IE_MOBILE_ID; - buf[1] = 1; - buf[2] = 0xf0; - break; - } - /* alter MI type */ - buf[2] = (buf[2] & ~GSM_MI_TYPE_MASK) | mi_type; - - if (msg) { - /* MI as LV */ - ie = msgb_put(msg, 1 + buf[1]); - memcpy(ie, buf + 1, 1 + buf[1]); + msgb_put_u8(msg, 1); + msgb_put_u8(msg, 0xf0 | mi_type); } return 0; @@ -1816,7 +1834,6 @@ { struct msgb *nmsg; struct gsm48_hdr *ngh; - uint8_t buf[11]; LOGP(DMM, LOGL_INFO, "IDENTITY RESPONSE\n"); @@ -1828,8 +1845,8 @@ ngh->proto_discr = GSM48_PDISC_MM; ngh->msg_type = GSM48_MT_MM_ID_RESP; - /* MI */ - gsm48_encode_mi(buf, nmsg, ms, mi_type); + /* MI (LV) */ + gsm48_encode_mi(ms, nmsg, false, mi_type, false); /* push RR header and send down */ return gsm48_mm_to_rr(ms, nmsg, GSM48_RR_DATA_REQ, 0, 0); @@ -1847,7 +1864,6 @@ struct msgb *nmsg; struct gsm48_hdr *ngh; uint8_t pwr_lev; - uint8_t buf[11]; struct gsm48_classmark1 cm; @@ -1868,13 +1884,13 @@ pwr_lev = gsm48_current_pwr_lev(set, rr->cd_now.arfcn); gsm48_encode_classmark1(&cm, sup->rev_lev, sup->es_ind, set->a5_1, pwr_lev); - msgb_v_put(nmsg, *((uint8_t *)&cm)); - /* MI */ + msgb_v_put(nmsg, *((uint8_t *)&cm)); + /* MI (LV) */ if (subscr->tmsi != GSM_RESERVED_TMSI) { /* have TMSI ? */ - gsm48_encode_mi(buf, nmsg, ms, GSM_MI_TYPE_TMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_TMSI, false); LOGP(DMM, LOGL_INFO, " using TMSI 0x%08x\n", subscr->tmsi); } else { - gsm48_encode_mi(buf, nmsg, ms, GSM_MI_TYPE_IMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMSI, false); LOGP(DMM, LOGL_INFO, " using IMSI %s\n", subscr->imsi); } @@ -2372,7 +2388,6 @@ struct gsm48_hdr *ngh; struct gsm48_loc_upd_req *nlu; /* NOTE: mi_len is part of struct */ uint8_t pwr_lev; - uint8_t buf[11]; LOGP(DMM, LOGL_INFO, "LOCATION UPDATING REQUEST\n"); @@ -2380,7 +2395,8 @@ if (!nmsg) return -ENOMEM; ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh)); - nlu = (struct gsm48_loc_upd_req *)msgb_put(nmsg, sizeof(*nlu)); + /* Do not add mi_len to the message, this is done at gsm48_encode_mi(). */ + nlu = (struct gsm48_loc_upd_req *)msgb_put(nmsg, sizeof(*nlu) - 1); ngh->proto_discr = GSM48_PDISC_MM; ngh->msg_type = GSM48_MT_MM_LOC_UPD_REQUEST; @@ -2399,16 +2415,14 @@ pwr_lev = gsm48_current_pwr_lev(set, cs->sel_arfcn); gsm48_encode_classmark1(&nlu->classmark1, sup->rev_lev, sup->es_ind, set->a5_1, pwr_lev); - /* MI */ + /* MI (LV) */ if (subscr->tmsi != GSM_RESERVED_TMSI) { /* have TMSI ? */ - gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_TMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_TMSI, false); LOGP(DMM, LOGL_INFO, " using TMSI 0x%08x\n", subscr->tmsi); } else { - gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMSI, false); LOGP(DMM, LOGL_INFO, " using IMSI %s\n", subscr->imsi); } - msgb_put(nmsg, buf[1]); /* length is part of nlu */ - memcpy(&nlu->mi_len, buf + 1, 1 + buf[1]); new_mm_state(mm, GSM48_MM_ST_WAIT_RR_CONN_LUPD, 0); @@ -2826,7 +2840,6 @@ struct gsm48_hdr *ngh; struct gsm48_service_request *nsr; /* NOTE: includes MI length */ uint8_t *cm2lv; - uint8_t buf[11]; LOGP(DMM, LOGL_INFO, "CM SERVICE REQUEST (cause %d)\n", mm->est_cause); @@ -2834,7 +2847,8 @@ if (!nmsg) return -ENOMEM; ngh = (struct gsm48_hdr *)msgb_put(nmsg, sizeof(*ngh)); - nsr = (struct gsm48_service_request *)msgb_put(nmsg, sizeof(*nsr)); + /* Do not add mi_len to the message, this is done at gsm48_encode_mi(). */ + nsr = (struct gsm48_service_request *)msgb_put(nmsg, sizeof(*nsr) - 1); cm2lv = (uint8_t *)&nsr->classmark; ngh->proto_discr = GSM48_PDISC_MM; @@ -2852,23 +2866,21 @@ if (mm->est_cause == RR_EST_CAUSE_EMERGENCY && set->emergency_imsi[0]) { LOGP(DMM, LOGL_INFO, "-> Using IMSI %s for emergency\n", set->emergency_imsi); - gsm48_generate_mid_from_imsi(buf, set->emergency_imsi); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMSI, true); } else if (!subscr->sim_valid) { /* have no SIM ? */ LOGP(DMM, LOGL_INFO, "-> Using IMEI %s\n", set->imei); - gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMEI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMEI, false); } else if (subscr->tmsi != GSM_RESERVED_TMSI) { /* have TMSI ? */ - gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_TMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_TMSI, false); LOGP(DMM, LOGL_INFO, "-> Using TMSI\n"); } else { - gsm48_encode_mi(buf, NULL, ms, GSM_MI_TYPE_IMSI); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMSI, false); LOGP(DMM, LOGL_INFO, "-> Using IMSI %s\n", subscr->imsi); } - msgb_put(nmsg, buf[1]); /* length is part of nsr */ - memcpy(&nsr->mi_len, buf + 1, 1 + buf[1]); /* prio is optional for eMLPP */ /* push RR header and send down */ diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 1984d26..8c3bbd8 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -921,11 +921,9 @@ /* send chiperhing mode complete */ static int gsm48_rr_tx_cip_mode_cpl(struct osmocom_ms *ms, uint8_t cr) { - struct gsm_settings *set = &ms->settings; struct msgb *nmsg; struct gsm48_hdr *gh; struct gsm48_rr_hdr *nrrh; - uint8_t buf[11], *tlv; LOGP(DRR, LOGL_INFO, "CIPHERING MODE COMPLETE (cr %d)\n", cr); @@ -938,13 +936,8 @@ gh->msg_type = GSM48_MT_RR_CIPH_M_COMPL; /* MI */ - if (cr) { - gsm48_generate_mid_from_imsi(buf, set->imeisv); - /* alter MI type */ - buf[2] = (buf[2] & ~GSM_MI_TYPE_MASK) | GSM_MI_TYPE_IMEISV; - tlv = msgb_put(nmsg, 2 + buf[1]); - memcpy(tlv, buf, 2 + buf[1]); - } + if (cr) + gsm48_encode_mi(ms, nmsg, true, GSM_MI_TYPE_IMEISV, false); gsm48_send_rsl(ms, RSL_MT_DATA_REQ, nmsg, 0); @@ -3208,12 +3201,11 @@ static int gsm48_rr_dl_est(struct osmocom_ms *ms) { struct gsm48_rrlayer *rr = &ms->rrlayer; - struct gsm322_cellsel *cs = &ms->cellsel; struct gsm_subscriber *subscr = &ms->subscr; + struct gsm322_cellsel *cs = &ms->cellsel; struct msgb *nmsg; struct gsm48_hdr *gh; struct gsm48_pag_rsp *pr; - uint8_t mi[11]; uint16_t ma[64]; uint8_t ma_len; @@ -3290,21 +3282,18 @@ if (ms->subscr.tmsi != GSM_RESERVED_TMSI && (osmo_lai_cmp(&ms->subscr.lai, &cs->sel_cgi.lai) == 0) && rr->paging_mi_type == GSM_MI_TYPE_TMSI) { - gsm48_generate_mid_from_tmsi(mi, subscr->tmsi); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_TMSI, false); LOGP(DRR, LOGL_INFO, "sending paging response with " "TMSI\n"); } else if (subscr->imsi[0]) { - gsm48_generate_mid_from_imsi(mi, subscr->imsi); + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_IMSI, false); LOGP(DRR, LOGL_INFO, "sending paging response with " "IMSI\n"); } else { - mi[1] = 1; - mi[2] = 0xf0 | GSM_MI_TYPE_NONE; + gsm48_encode_mi(ms, nmsg, false, GSM_MI_TYPE_NONE, false); LOGP(DRR, LOGL_INFO, "sending paging response without " "TMSI/IMSI\n"); } - msgb_put(nmsg, 1 + mi[1]); - memcpy(pr->data, mi + 1, 1 + mi[1]); } #ifdef TEST_FREQUENCY_MOD -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34484?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I9ff429bd50d718530fdad64a276053a35c8928f2 Gerrit-Change-Number: 34484 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: Fix request reference value in gsm48_match_ra()
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34486?usp=email
) Change subject: Fix request reference value in gsm48_match_ra() ...................................................................... Fix request reference value in gsm48_match_ra() Do not overwrite the given request reference pointer with the history buffer's reference. This makes no sense. Without this fix only the response to the first access burst could be matched correctly. Change-Id: Iec636d368e20030beac2861bff61b1a06e7b4821 --- M src/host/layer23/src/mobile/gsm48_rr.c 1 file changed, 21 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/86/34486/1 diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 08b208f..c8aa921 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -2374,13 +2374,12 @@ for (i = 0; i < hist_num; i++) { /* filter confirmed RACH requests only */ if (rr->cr_hist[i].valid && ref->ra == rr->cr_hist[i].ref.ra) { - ia_t1 = ref->t1; - ia_t2 = ref->t2; - ia_t3 = (ref->t3_high << 3) | ref->t3_low; - ref = &rr->cr_hist[i].ref; - cr_t1 = ref->t1; - cr_t2 = ref->t2; - cr_t3 = (ref->t3_high << 3) | ref->t3_low; + ia_t1 = ref->t1; + ia_t2 = ref->t2; + ia_t3 = (ref->t3_high << 3) | ref->t3_low; + cr_t1 = rr->cr_hist[i].ref.t1; + cr_t2 = rr->cr_hist[i].ref.t2; + cr_t3 = (rr->cr_hist[i].ref.t3_high << 3) | rr->cr_hist[i].ref.t3_low; if (ia_t1 == cr_t1 && ia_t2 == cr_t2 && ia_t3 == cr_t3) { LOGP(DRR, LOGL_INFO, "request %02x matches " -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34486?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: Iec636d368e20030beac2861bff61b1a06e7b4821 Gerrit-Change-Number: 34486 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: ASCI: Increase channel request history to 5 entries
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34485?usp=email
) Change subject: ASCI: Increase channel request history to 5 entries ...................................................................... ASCI: Increase channel request history to 5 entries 3 entries are enough for random access on CCCH. 5 are required for uplink request on VGCS channel. The history is used to remember when the random access bursts were send. The RR layer can check if the IMMEDIATE ASSIGNMENT or VGCS UPLINK GRANT message has matching frame number and random value of up to 5 random access bursts previously sent. Related: OS#5364 Change-Id: I62f18685bf05663f3ee6e94f6884ffb9a6b07ea4 --- M src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h M src/host/layer23/src/mobile/gsm48_rr.c 2 files changed, 25 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/85/34485/1 diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h index 299b6e5..fb07cc9 100644 --- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h +++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_rr.h @@ -159,7 +159,7 @@ /* cr_hist */ uint8_t cr_ra; /* stores requested ra until confirmed */ - struct gsm48_cr_hist cr_hist[3]; + struct gsm48_cr_hist cr_hist[5]; /* V(SD) sequence numbers */ uint16_t v_sd; /* 16 PD 1-bit sequence numbers packed */ diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index 8c3bbd8..08b208f 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -2364,14 +2364,14 @@ */ /* match request reference against request history */ -static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref) +static int gsm48_match_ra(struct osmocom_ms *ms, struct gsm48_req_ref *ref, int hist_num) { struct gsm48_rrlayer *rr = &ms->rrlayer; int i; uint8_t ia_t1, ia_t2, ia_t3; uint8_t cr_t1, cr_t2, cr_t3; - for (i = 0; i < 3; i++) { + for (i = 0; i < hist_num; i++) { /* filter confirmed RACH requests only */ if (rr->cr_hist[i].valid && ref->ra == rr->cr_hist[i].ref.ra) { ia_t1 = ref->t1; @@ -2492,7 +2492,7 @@ } /* request ref */ - if (gsm48_match_ra(ms, &ia->req_ref)) { + if (gsm48_match_ra(ms, &ia->req_ref, 3)) { /* channel description */ memcpy(&rr->cd_now, &cd, sizeof(rr->cd_now)); /* timing advance */ @@ -2640,7 +2640,7 @@ } /* request ref 1 */ - if (gsm48_match_ra(ms, &ia->req_ref1)) { + if (gsm48_match_ra(ms, &ia->req_ref1, 3)) { /* channel description */ memcpy(&rr->cd_now, &cd1, sizeof(rr->cd_now)); /* timing advance */ @@ -2656,7 +2656,7 @@ return gsm48_rr_dl_est(ms); } /* request ref 2 */ - if (gsm48_match_ra(ms, &ia->req_ref2)) { + if (gsm48_match_ra(ms, &ia->req_ref2, 3)) { /* channel description */ memcpy(&rr->cd_now, &cd2, sizeof(rr->cd_now)); /* timing advance */ @@ -2706,7 +2706,7 @@ (((uint8_t *)&ia->req_ref1) + i * 4); LOGP(DRR, LOGL_INFO, "IMMEDIATE ASSIGNMENT REJECT " "(ref 0x%02x)\n", req_ref->ra); - if (gsm48_match_ra(ms, req_ref)) { + if (gsm48_match_ra(ms, req_ref, 3)) { /* wait indication */ t3122_value = *(((uint8_t *)&ia->wait_ind1) + i * 4); if (t3122_value) -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34485?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I62f18685bf05663f3ee6e94f6884ffb9a6b07ea4 Gerrit-Change-Number: 34485 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
[S] Change in osmocom-bb[master]: Fix unset sapi in gsm48_rr_data_ind()
by jolly
jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmocom-bb/+/34487?usp=email
) Change subject: Fix unset sapi in gsm48_rr_data_ind() ...................................................................... Fix unset sapi in gsm48_rr_data_ind() The gsm48_rr_hdr is pushed into the message before sending data to MM layer. SAPI was not set in this header. Change-Id: I8345a562050d52d491f3b7192c979d455a63931c --- M src/host/layer23/src/mobile/gsm48_rr.c 1 file changed, 15 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/87/34487/1 diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c index c8aa921..47817a7 100644 --- a/src/host/layer23/src/mobile/gsm48_rr.c +++ b/src/host/layer23/src/mobile/gsm48_rr.c @@ -4729,6 +4729,8 @@ /* 3.4.2 data from layer 2 to RR and upper layer*/ static int gsm48_rr_data_ind(struct osmocom_ms *ms, struct msgb *msg) { + struct abis_rsl_rll_hdr *rllh = msgb_l2(msg); + uint8_t sapi = rllh->link_id & 7; struct gsm48_hdr *gh = msgb_l3(msg); struct gsm48_rr_hdr *rrh; uint8_t pdisc = gh->proto_discr & 0x0f; @@ -4794,6 +4796,7 @@ msgb_push(msg, sizeof(struct gsm48_rr_hdr)); rrh = (struct gsm48_rr_hdr *)msg->data; rrh->msg_type = GSM48_RR_DATA_IND; + rrh->sapi = sapi; return gsm48_rr_upmsg(ms, msg); } -- To view, visit
https://gerrit.osmocom.org/c/osmocom-bb/+/34487?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I8345a562050d52d491f3b7192c979d455a63931c Gerrit-Change-Number: 34487 Gerrit-PatchSet: 1 Gerrit-Owner: jolly <andreas(a)eversberg.eu> Gerrit-MessageType: newchange
1 year, 9 months
1
0
0
0
← Newer
1
...
76
77
78
79
80
81
82
...
195
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
Results per page:
10
25
50
100
200