[layer23/mobile] Improvement and fixes of idle mode process
[osmocom-bb.git] / src / host / layer23 / include / osmocom / bb / mobile / gsm322.h
1 #ifndef _GSM322_H
2 #define _GSM322_H
3
4 /* 4.3.1.1 List of states for PLMN slection process (automatic mode) */
5 #define GSM322_A0_NULL                  0
6 #define GSM322_A1_TRYING_RPLMN          1
7 #define GSM322_A2_ON_PLMN               2
8 #define GSM322_A3_TRYING_PLMN           3
9 #define GSM322_A4_WAIT_FOR_PLMN         4
10 #define GSM322_A5_HPLMN_SEARCH          5
11 #define GSM322_A6_NO_SIM                6
12
13 /* 4.3.1.2 List of states for PLMN slection process (manual mode) */
14 #define GSM322_M0_NULL                  0
15 #define GSM322_M1_TRYING_RPLMN          1
16 #define GSM322_M2_ON_PLMN               2
17 #define GSM322_M3_NOT_ON_PLMN           3
18 #define GSM322_M4_TRYING_PLMN           4
19 #define GSM322_M5_NO_SIM                5
20
21 /* 4.3.2 List of states for cell selection process */
22 #define GSM322_C0_NULL                  0
23 #define GSM322_C1_NORMAL_CELL_SEL       1
24 #define GSM322_C2_STORED_CELL_SEL       2
25 #define GSM322_C3_CAMPED_NORMALLY       3
26 #define GSM322_C4_NORMAL_CELL_RESEL     4
27 #define GSM322_C5_CHOOSE_CELL           5
28 #define GSM322_C6_ANY_CELL_SEL          6
29 #define GSM322_C7_CAMPED_ANY_CELL       7
30 #define GSM322_C8_ANY_CELL_RESEL        8
31 #define GSM322_C9_CHOOSE_ANY_CELL       9
32 #define GSM322_CONNECTED_MODE_1         10
33 #define GSM322_CONNECTED_MODE_2         11
34 #define GSM322_PLMN_SEARCH              12
35 #define GSM322_HPLMN_SEARCH             13
36 #define GSM322_ANY_SEARCH               14
37
38 /* GSM 03.22 events */
39 #define GSM322_EVENT_SWITCH_ON          1
40 #define GSM322_EVENT_SWITCH_OFF         2       
41 #define GSM322_EVENT_SIM_INSERT         3
42 #define GSM322_EVENT_SIM_REMOVE         4
43 #define GSM322_EVENT_REG_SUCCESS        5
44 #define GSM322_EVENT_REG_FAILED         6
45 #define GSM322_EVENT_ROAMING_NA         7
46 #define GSM322_EVENT_INVALID_SIM        8
47 #define GSM322_EVENT_NEW_PLMN           9
48 #define GSM322_EVENT_ON_PLMN            10
49 #define GSM322_EVENT_PLMN_SEARCH_START  11
50 #define GSM322_EVENT_PLMN_SEARCH_END    12
51 #define GSM322_EVENT_USER_RESEL         13
52 #define GSM322_EVENT_PLMN_AVAIL         14
53 #define GSM322_EVENT_CHOOSE_PLMN        15
54 #define GSM322_EVENT_SEL_MANUAL         16
55 #define GSM322_EVENT_SEL_AUTO           17
56 #define GSM322_EVENT_CELL_FOUND         18
57 #define GSM322_EVENT_NO_CELL_FOUND      19
58 #define GSM322_EVENT_LEAVE_IDLE         20
59 #define GSM322_EVENT_RET_IDLE           21
60 #define GSM322_EVENT_CELL_RESEL         22
61 #define GSM322_EVENT_SYSINFO            23
62 #define GSM322_EVENT_HPLMN_SEARCH       24
63
64 enum {
65         PLMN_MODE_MANUAL,
66         PLMN_MODE_AUTO
67 };
68
69 /* node for each PLMN */
70 struct gsm322_plmn_list {
71         struct llist_head       entry;
72         uint16_t                mcc, mnc;
73         int8_t                  rxlev; /* rx level in range format */
74         uint8_t                 cause; /* cause value, if PLMN is not allowed */
75 };
76
77 /* node for each forbidden LA */
78 struct gsm322_la_list {
79         struct llist_head       entry;
80         uint16_t                mcc, mnc, lac;
81         uint8_t                 cause;
82 };
83
84 /* node for each BA-List */
85 struct gsm322_ba_list {
86         struct llist_head       entry;
87         uint16_t                mcc, mnc;
88         /* Band allocation for 1024+299 frequencies.
89          * First bit of first index is frequency 0.
90          */
91         uint8_t                 freq[128+38];
92 };
93
94 #define GSM322_CS_FLAG_SUPPORT  0x01 /* frequency is supported by radio */
95 #define GSM322_CS_FLAG_BA       0x02 /* frequency is part of the current ba */
96 #define GSM322_CS_FLAG_POWER    0x04 /* frequency was power scanned */
97 #define GSM322_CS_FLAG_SIGNAL   0x08 /* valid signal detected */
98 #define GSM322_CS_FLAG_SYSINFO  0x10 /* complete sysinfo received */
99 #define GSM322_CS_FLAG_BARRED   0x20 /* cell is barred */
100 #define GSM322_CS_FLAG_FORBIDD  0x40 /* cell in list of forbidden LAs */
101 #define GSM322_CS_FLAG_TEMP_AA  0x80 /* if temporary available and allowable */
102
103 /* Cell selection list */
104 struct gsm322_cs_list {
105         uint8_t                 flags; /* see GSM322_CS_FLAG_* */
106         int8_t                  rxlev; /* rx level range format */
107         struct gsm48_sysinfo    *sysinfo;
108 };
109
110 /* PLMN search process */
111 struct gsm322_plmn {
112         struct osmocom_ms       *ms;
113         int                     state; /* GSM322_Ax_* or GSM322_Mx_* */
114
115         struct llist_head       event_queue; /* event messages */
116         struct llist_head       sorted_plmn; /* list of sorted PLMN */
117         struct llist_head       forbidden_la; /* forbidden LAs */
118
119         struct osmo_timer_list  timer;
120
121         int                     plmn_curr; /* current index in sorted_plmn */
122         uint16_t                mcc, mnc; /* current network selected */
123 };
124
125 /* state of CCCH activation */
126 #define GSM322_CCCH_ST_IDLE     0       /* no connection */
127 #define GSM322_CCCH_ST_INIT     1       /* initalized */
128 #define GSM322_CCCH_ST_SYNC     2       /* got sync */
129 #define GSM322_CCCH_ST_DATA     3       /* receiveing data */
130
131 /* neighbour cell info list entry */
132 struct gsm322_neighbour {
133         struct llist_head       entry;
134         struct gsm322_cellsel   *cs;
135         uint16_t                arfcn; /* ARFCN identity of that neighbour */
136
137         uint8_t                 state; /* GSM322_NB_* */
138         time_t                  created; /* when was this neighbour created */
139         time_t                  when; /* when did we sync / read */
140         int16_t                 rxlev_dbm; /* sum of received levels */
141         uint8_t                 rxlev_count; /* number of received levels */
142         int8_t                  rla_c_dbm; /* average of the reveive level */
143         uint8_t                 c12_valid; /* both C1 and C2 are calculated */
144         int16_t                 c1, c2, crh;
145         uint8_t                 checked_for_resel;
146         uint8_t                 suitable_allowable;
147         uint8_t                 prio_low;
148 };
149
150 #define GSM322_NB_NEW           0       /* new NB instance */
151 #define GSM322_NB_NOT_SUP       1       /* ARFCN not supported */
152 #define GSM322_NB_RLA_C         2       /* valid measurement available */
153 #define GSM322_NB_NO_SYNC       3       /* cannot sync to neighbour */
154 #define GSM322_NB_NO_BCCH       4       /* sync */
155 #define GSM322_NB_SYSINFO       5       /* sysinfo */
156
157 struct gsm48_sysinfo;
158 /* Cell selection process */
159 struct gsm322_cellsel {
160         struct osmocom_ms       *ms;
161         int                     state; /* GSM322_Cx_* */
162
163         struct llist_head       event_queue; /* event messages */
164         struct llist_head       ba_list; /* BCCH Allocation per PLMN */
165         struct gsm322_cs_list   list[1024+299];
166                                         /* cell selection list per frequency. */
167         /* scan and tune state */
168         struct osmo_timer_list  timer; /* cell selection timer */
169         uint16_t                mcc, mnc; /* current network to search for */
170         uint8_t                 powerscan; /* currently scanning for power */
171         uint8_t                 ccch_state; /* special state of current ccch */
172         uint32_t                scan_state; /* special state of current scan */
173         uint16_t                arfcn; /* current tuned idle mode arfcn */
174         int                     arfci; /* list index of frequency above */
175         uint8_t                 ccch_mode; /* curren CCCH_MODE_* */
176         uint8_t                 sync_retries; /* number retries to sync */
177         uint8_t                 sync_pending; /* to prevent double sync req. */
178         struct gsm48_sysinfo    *si; /* current sysinfo of tuned cell */
179         uint8_t                 tuned; /* if a cell is selected */
180         struct osmo_timer_list  any_timer; /* restart search 'any cell' */
181
182         /* serving cell */
183         uint8_t                 selected; /* if a cell is selected */
184         uint16_t                sel_arfcn; /* current selected serving cell! */
185         struct gsm48_sysinfo    sel_si; /* copy of selected cell, will update */
186         uint16_t                sel_mcc, sel_mnc, sel_lac, sel_id;
187
188         /* cell re-selection */
189         struct llist_head       nb_list; /* list of neighbour cells */
190         uint16_t                last_serving_arfcn; /* the ARFCN of last cell */
191         uint8_t                 last_serving_valid; /* there is a last cell */
192         struct gsm322_neighbour *neighbour; /* when selecting neighbour cell */
193         time_t                  resel_when; /* timestamp of last re-selection */
194         int8_t                  nb_meas_set;
195         int16_t                 rxlev_dbm; /* sum of received levels */
196         uint8_t                 rxlev_count; /* number of received levels */
197         int8_t                  rla_c_dbm; /* average of received level */
198         uint8_t                 c12_valid; /* both C1 and C2 values are
199                                                 calculated */
200         int16_t                 c1, c2;
201         uint8_t                 prio_low;
202 };
203
204 /* GSM 03.22 message */
205 struct gsm322_msg {
206         int                     msg_type;
207         uint16_t                mcc, mnc;
208         uint8_t                 sysinfo; /* system information type */
209         uint8_t                 same_cell; /* select same cell when RET_IDLE */
210         uint8_t                 reject; /* location update reject cause */
211         uint8_t                 limited; /* trigger search for limited serv. */
212 };
213
214 #define GSM322_ALLOC_SIZE       sizeof(struct gsm322_msg)
215 #define GSM322_ALLOC_HEADROOM   0
216
217 uint16_t index2arfcn(int index);
218 int arfcn2index(uint16_t arfcn);
219 int gsm322_init(struct osmocom_ms *ms);
220 int gsm322_exit(struct osmocom_ms *ms);
221 struct msgb *gsm322_msgb_alloc(int msg_type);
222 int gsm322_plmn_sendmsg(struct osmocom_ms *ms, struct msgb *msg);
223 int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg);
224 int gsm322_c_event(struct osmocom_ms *ms, struct msgb *msg);
225 int gsm322_plmn_dequeue(struct osmocom_ms *ms);
226 int gsm322_cs_dequeue(struct osmocom_ms *ms);
227 int gsm322_add_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
228         uint16_t mnc, uint16_t lac, uint8_t cause);
229 int gsm322_del_forbidden_la(struct osmocom_ms *ms, uint16_t mcc,
230         uint16_t mnc, uint16_t lac);
231 int gsm322_is_forbidden_la(struct osmocom_ms *ms, uint16_t mcc, uint16_t mnc,
232         uint16_t lac);
233 int gsm322_dump_sorted_plmn(struct osmocom_ms *ms);
234 int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
235                         void (*print)(void *, const char *, ...), void *priv);
236 int gsm322_dump_forbidden_la(struct osmocom_ms *ms,
237                         void (*print)(void *, const char *, ...), void *priv);
238 int gsm322_dump_ba_list(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc,
239                         void (*print)(void *, const char *, ...), void *priv);
240 int gsm322_dump_nb_list(struct gsm322_cellsel *cs,
241                         void (*print)(void *, const char *, ...), void *priv);
242 void start_cs_timer(struct gsm322_cellsel *cs, int sec, int micro);
243 void start_loss_timer(struct gsm322_cellsel *cs, int sec, int micro);
244 const char *get_a_state_name(int value);
245 const char *get_m_state_name(int value);
246 const char *get_cs_state_name(int value);
247 int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
248                      void *handler_data, void *signal_data);
249
250 int gsm322_meas(struct osmocom_ms *ms, uint8_t rx_lev);
251
252 char *gsm_print_rxlev(uint8_t rxlev);
253
254
255 #endif /* _GSM322_H */