layer23: Pre-rework of the Makefile.am
[osmocom-bb.git] / src / host / layer23 / src / layer3.c
1 #include <stdint.h>
2 #include <errno.h>
3 #include <stdio.h>
4
5 #include <osmocore/msgb.h>
6 #include <osmocore/rsl.h>
7 #include <osmocore/tlv.h>
8 #include <osmocore/protocol/gsm_04_08.h>
9
10 #include <osmocom/logging.h>
11 #include <osmocom/lapdm.h>
12 #include <osmocom/rslms.h>
13 #include <osmocom/layer3.h>
14 #include <osmocom/osmocom_data.h>
15 #include <osmocom/l1ctl.h>
16
17 static int ccch_mode = CCCH_MODE_NONE;
18
19 static void dump_bcch(struct osmocom_ms *ms, uint8_t tc, const uint8_t *data)
20 {
21         struct gsm48_system_information_type_header *si_hdr;
22         si_hdr = (struct gsm48_system_information_type_header *) data;
23
24         /* GSM 05.02 ยง6.3.1.3 Mapping of BCCH data */
25         switch (si_hdr->system_information) {
26         case GSM48_MT_RR_SYSINFO_1:
27                 fprintf(stderr, "\tSI1");
28 #ifdef BCCH_TC_CHECK
29                 if (tc != 0)
30                         fprintf(stderr, " on wrong TC");
31 #endif
32                 break;
33         case GSM48_MT_RR_SYSINFO_2:
34                 fprintf(stderr, "\tSI2");
35 #ifdef BCCH_TC_CHECK
36                 if (tc != 1)
37                         fprintf(stderr, " on wrong TC");
38 #endif
39                 break;
40         case GSM48_MT_RR_SYSINFO_3:
41                 fprintf(stderr, "\tSI3");
42 #ifdef BCCH_TC_CHECK
43                 if (tc != 2 && tc != 6)
44                         fprintf(stderr, " on wrong TC");
45 #endif
46                 if (ccch_mode == CCCH_MODE_NONE) {
47                         struct gsm48_system_information_type_3 *si3 =
48                                 (struct gsm48_system_information_type_3 *)data;
49
50                         if (si3->control_channel_desc.ccch_conf == RSL_BCCH_CCCH_CONF_1_C)
51                                 ccch_mode = CCCH_MODE_COMBINED;
52                         else
53                                 ccch_mode = CCCH_MODE_NON_COMBINED;
54
55                         l1ctl_tx_ccch_mode_req(ms, ccch_mode);
56                 }
57                 break;
58         case GSM48_MT_RR_SYSINFO_4:
59                 fprintf(stderr, "\tSI4");
60 #ifdef BCCH_TC_CHECK
61                 if (tc != 3 && tc != 7)
62                         fprintf(stderr, " on wrong TC");
63 #endif
64                 break;
65         case GSM48_MT_RR_SYSINFO_5:
66                 fprintf(stderr, "\tSI5");
67                 break;
68         case GSM48_MT_RR_SYSINFO_6:
69                 fprintf(stderr, "\tSI6");
70                 break;
71         case GSM48_MT_RR_SYSINFO_7:
72                 fprintf(stderr, "\tSI7");
73 #ifdef BCCH_TC_CHECK
74                 if (tc != 7)
75                         fprintf(stderr, " on wrong TC");
76 #endif
77                 break;
78         case GSM48_MT_RR_SYSINFO_8:
79                 fprintf(stderr, "\tSI8");
80 #ifdef BCCH_TC_CHECK
81                 if (tc != 3)
82                         fprintf(stderr, " on wrong TC");
83 #endif
84                 break;
85         case GSM48_MT_RR_SYSINFO_9:
86                 fprintf(stderr, "\tSI9");
87 #ifdef BCCH_TC_CHECK
88                 if (tc != 4)
89                         fprintf(stderr, " on wrong TC");
90 #endif
91                 break;
92         case GSM48_MT_RR_SYSINFO_13:
93                 fprintf(stderr, "\tSI13");
94 #ifdef BCCH_TC_CHECK
95                 if (tc != 4 && tc != 0)
96                         fprintf(stderr, " on wrong TC");
97 #endif
98                 break;
99         case GSM48_MT_RR_SYSINFO_16:
100                 fprintf(stderr, "\tSI16");
101 #ifdef BCCH_TC_CHECK
102                 if (tc != 6)
103                         fprintf(stderr, " on wrong TC");
104 #endif
105                 break;
106         case GSM48_MT_RR_SYSINFO_17:
107                 fprintf(stderr, "\tSI17");
108 #ifdef BCCH_TC_CHECK
109                 if (tc != 2)
110                         fprintf(stderr, " on wrong TC");
111 #endif
112                 break;
113         case GSM48_MT_RR_SYSINFO_2bis:
114                 fprintf(stderr, "\tSI2bis");
115 #ifdef BCCH_TC_CHECK
116                 if (tc != 5)
117                         fprintf(stderr, " on wrong TC");
118 #endif
119                 break;
120         case GSM48_MT_RR_SYSINFO_2ter:
121                 fprintf(stderr, "\tSI2ter");
122 #ifdef BCCH_TC_CHECK
123                 if (tc != 5 && tc != 4)
124                         fprintf(stderr, " on wrong TC");
125 #endif
126                 break;
127         case GSM48_MT_RR_SYSINFO_5bis:
128                 fprintf(stderr, "\tSI5bis");
129                 break;
130         case GSM48_MT_RR_SYSINFO_5ter:
131                 fprintf(stderr, "\tSI5ter");
132                 break;
133         default:
134                 fprintf(stderr, "\tUnknown SI");
135                 break;
136         };
137
138         fprintf(stderr, "\n");
139 }
140
141
142 /* send location updating request * (as part of RSLms EST IND /
143    LAPDm SABME) */
144 static int gsm48_tx_loc_upd_req(struct osmocom_ms *ms, uint8_t chan_nr)
145 {
146         struct msgb *msg = msgb_alloc_headroom(256, 16, "loc_upd_req");
147         struct gsm48_hdr *gh;
148         struct gsm48_loc_upd_req *lu_r;
149
150         DEBUGP(DMM, "chan_nr=%u\n", chan_nr);
151
152         msg->l3h = msgb_put(msg, sizeof(*gh));
153         gh = (struct gsm48_hdr *) msg->l3h;
154         gh->proto_discr = GSM48_PDISC_MM;
155         gh->msg_type = GSM48_MT_MM_LOC_UPD_REQUEST;
156         lu_r = (struct gsm48_loc_upd_req *) msgb_put(msg, sizeof(*lu_r));
157         lu_r->type = GSM48_LUPD_IMSI_ATT;
158         lu_r->key_seq = 0;
159         /* FIXME: set LAI and CM1 */
160         /* FIXME: set MI */
161         lu_r->mi_len = 0;
162
163         return rslms_tx_rll_req_l3(ms, RSL_MT_EST_REQ, chan_nr, 0, msg);
164 }
165
166 static int gsm48_rx_imm_ass(struct msgb *msg, struct osmocom_ms *ms)
167 {
168         struct gsm48_imm_ass *ia = msgb_l3(msg);
169         uint8_t ch_type, ch_subch, ch_ts;
170         uint16_t arfcn;
171
172         rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch, &ch_ts);
173         arfcn = ia->chan_desc.h0.arfcn_low | (ia->chan_desc.h0.arfcn_high << 8);
174
175         DEBUGP(DRR, "GSM48 IMM ASS (ra=0x%02x, chan_nr=0x%02x, "
176                 "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ", ia->req_ref.ra,
177                 ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
178                 ia->chan_desc.h0.tsc);
179
180         /* FIXME: compare RA and GSM time with when we sent RACH req */
181
182         /* check if we can support this type of channel at the moment */
183         if (ch_type != RSL_CHAN_SDCCH4_ACCH || ch_ts != 0 ||
184             ia->chan_desc.h0.h == 1) {
185                 DEBUGPC(DRR, "UNSUPPORTED!\n");
186                 return 0;
187         }
188
189         /* request L1 to go to dedicated mode on assigned channel */
190         tx_ph_dm_est_req_h0(ms, arfcn, ia->chan_desc.chan_nr,
191                          ia->chan_desc.h0.tsc);
192
193         /* request L2 to establish the SAPI0 connection */
194         gsm48_tx_loc_upd_req(ms, ia->chan_desc.chan_nr);
195
196         DEBUGPC(DRR, "\n");
197
198         return 0;
199 }
200
201 int gsm48_rx_ccch(struct msgb *msg, struct osmocom_ms *ms)
202 {
203         struct gsm48_system_information_type_header *sih = msgb_l3(msg);
204         int rc = 0;
205
206         if (sih->rr_protocol_discriminator != GSM48_PDISC_RR)
207                 LOGP(DRR, LOGL_ERROR, "PCH pdisc != RR\n");
208         
209         switch (sih->system_information) {
210         case GSM48_MT_RR_PAG_REQ_1:
211         case GSM48_MT_RR_PAG_REQ_2:
212         case GSM48_MT_RR_PAG_REQ_3:
213                 /* FIXME: implement decoding of paging request */
214                 break;
215         case GSM48_MT_RR_IMM_ASS:
216                 rc = gsm48_rx_imm_ass(msg, ms);
217                 break;
218         default:
219                 LOGP(DRR, LOGL_NOTICE, "unknown PCH/AGCH type 0x%02x\n",
220                         sih->system_information);
221                 rc = -EINVAL;
222         }
223
224         return rc;
225 }
226
227 int gsm48_rx_bcch(struct msgb *msg, struct osmocom_ms *ms)
228 {
229         /* FIXME: we have lost the gsm frame time until here, need to store it
230          * in some msgb context */
231         //dump_bcch(dl->time.tc, ccch->data);
232         dump_bcch(ms, 0, msg->l3h);
233
234         return 0;
235 }