import gsm0502_calc_paging_group() from openbsc
[osmocom-bb.git] / src / gsm / abis_nm.c
1 /* GSM Network Management (OML) messages on the A-bis interface
2  * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
3
4 /* (C) 2008-2011 by Harald Welte <laforge@gnumonks.org>
5  *
6  * All Rights Reserved
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22
23 #include <stdint.h>
24 #include <errno.h>
25
26 #include <osmocom/core/utils.h>
27 #include <osmocom/core/logging.h>
28 #include <osmocom/gsm/tlv.h>
29 #include <osmocom/gsm/gsm_utils.h>
30 #include <osmocom/gsm/protocol/gsm_12_21.h>
31 #include <osmocom/gsm/abis_nm.h>
32
33 /* unidirectional messages from BTS to BSC */
34 const enum abis_nm_msgtype abis_nm_reports[4] = {
35         NM_MT_SW_ACTIVATED_REP,
36         NM_MT_TEST_REP,
37         NM_MT_STATECHG_EVENT_REP,
38         NM_MT_FAILURE_EVENT_REP,
39 };
40
41 /* messages without ACK/NACK */
42 const enum abis_nm_msgtype abis_nm_no_ack_nack[3] = {
43         NM_MT_MEAS_RES_REQ,
44         NM_MT_STOP_MEAS,
45         NM_MT_START_MEAS,
46 };
47
48 /* Messages related to software load */
49 const enum abis_nm_msgtype abis_nm_sw_load_msgs[9] = {
50         NM_MT_LOAD_INIT_ACK,
51         NM_MT_LOAD_INIT_NACK,
52         NM_MT_LOAD_SEG_ACK,
53         NM_MT_LOAD_ABORT,
54         NM_MT_LOAD_END_ACK,
55         NM_MT_LOAD_END_NACK,
56         //NM_MT_SW_ACT_REQ,
57         NM_MT_ACTIVATE_SW_ACK,
58         NM_MT_ACTIVATE_SW_NACK,
59         NM_MT_SW_ACTIVATED_REP,
60 };
61
62 const enum abis_nm_msgtype abis_nm_nacks[33] = {
63         NM_MT_LOAD_INIT_NACK,
64         NM_MT_LOAD_END_NACK,
65         NM_MT_SW_ACT_REQ_NACK,
66         NM_MT_ACTIVATE_SW_NACK,
67         NM_MT_ESTABLISH_TEI_NACK,
68         NM_MT_CONN_TERR_SIGN_NACK,
69         NM_MT_DISC_TERR_SIGN_NACK,
70         NM_MT_CONN_TERR_TRAF_NACK,
71         NM_MT_DISC_TERR_TRAF_NACK,
72         NM_MT_CONN_MDROP_LINK_NACK,
73         NM_MT_DISC_MDROP_LINK_NACK,
74         NM_MT_SET_BTS_ATTR_NACK,
75         NM_MT_SET_RADIO_ATTR_NACK,
76         NM_MT_SET_CHAN_ATTR_NACK,
77         NM_MT_PERF_TEST_NACK,
78         NM_MT_SEND_TEST_REP_NACK,
79         NM_MT_STOP_TEST_NACK,
80         NM_MT_STOP_EVENT_REP_NACK,
81         NM_MT_REST_EVENT_REP_NACK,
82         NM_MT_CHG_ADM_STATE_NACK,
83         NM_MT_CHG_ADM_STATE_REQ_NACK,
84         NM_MT_REP_OUTST_ALARMS_NACK,
85         NM_MT_CHANGEOVER_NACK,
86         NM_MT_OPSTART_NACK,
87         NM_MT_REINIT_NACK,
88         NM_MT_SET_SITE_OUT_NACK,
89         NM_MT_CHG_HW_CONF_NACK,
90         NM_MT_GET_ATTR_NACK,
91         NM_MT_SET_ALARM_THRES_NACK,
92         NM_MT_BS11_BEGIN_DB_TX_NACK,
93         NM_MT_BS11_END_DB_TX_NACK,
94         NM_MT_BS11_CREATE_OBJ_NACK,
95         NM_MT_BS11_DELETE_OBJ_NACK,
96 };
97
98 static const struct value_string nack_names[] = {
99         { NM_MT_LOAD_INIT_NACK,         "SOFTWARE LOAD INIT" },
100         { NM_MT_LOAD_END_NACK,          "SOFTWARE LOAD END" },
101         { NM_MT_SW_ACT_REQ_NACK,        "SOFTWARE ACTIVATE REQUEST" },
102         { NM_MT_ACTIVATE_SW_NACK,       "ACTIVATE SOFTWARE" },
103         { NM_MT_ESTABLISH_TEI_NACK,     "ESTABLISH TEI" },
104         { NM_MT_CONN_TERR_SIGN_NACK,    "CONNECT TERRESTRIAL SIGNALLING" },
105         { NM_MT_DISC_TERR_SIGN_NACK,    "DISCONNECT TERRESTRIAL SIGNALLING" },
106         { NM_MT_CONN_TERR_TRAF_NACK,    "CONNECT TERRESTRIAL TRAFFIC" },
107         { NM_MT_DISC_TERR_TRAF_NACK,    "DISCONNECT TERRESTRIAL TRAFFIC" },
108         { NM_MT_CONN_MDROP_LINK_NACK,   "CONNECT MULTI-DROP LINK" },
109         { NM_MT_DISC_MDROP_LINK_NACK,   "DISCONNECT MULTI-DROP LINK" },
110         { NM_MT_SET_BTS_ATTR_NACK,      "SET BTS ATTRIBUTE" },
111         { NM_MT_SET_RADIO_ATTR_NACK,    "SET RADIO ATTRIBUTE" },
112         { NM_MT_SET_CHAN_ATTR_NACK,     "SET CHANNEL ATTRIBUTE" },
113         { NM_MT_PERF_TEST_NACK,         "PERFORM TEST" },
114         { NM_MT_SEND_TEST_REP_NACK,     "SEND TEST REPORT" },
115         { NM_MT_STOP_TEST_NACK,         "STOP TEST" },
116         { NM_MT_STOP_EVENT_REP_NACK,    "STOP EVENT REPORT" },
117         { NM_MT_REST_EVENT_REP_NACK,    "RESET EVENT REPORT" },
118         { NM_MT_CHG_ADM_STATE_NACK,     "CHANGE ADMINISTRATIVE STATE" },
119         { NM_MT_CHG_ADM_STATE_REQ_NACK,
120                                 "CHANGE ADMINISTRATIVE STATE REQUEST" },
121         { NM_MT_REP_OUTST_ALARMS_NACK,  "REPORT OUTSTANDING ALARMS" },
122         { NM_MT_CHANGEOVER_NACK,        "CHANGEOVER" },
123         { NM_MT_OPSTART_NACK,           "OPSTART" },
124         { NM_MT_REINIT_NACK,            "REINIT" },
125         { NM_MT_SET_SITE_OUT_NACK,      "SET SITE OUTPUT" },
126         { NM_MT_CHG_HW_CONF_NACK,       "CHANGE HARDWARE CONFIGURATION" },
127         { NM_MT_GET_ATTR_NACK,          "GET ATTRIBUTE" },
128         { NM_MT_SET_ALARM_THRES_NACK,   "SET ALARM THRESHOLD" },
129         { NM_MT_BS11_BEGIN_DB_TX_NACK,  "BS11 BEGIN DATABASE TRANSMISSION" },
130         { NM_MT_BS11_END_DB_TX_NACK,    "BS11 END DATABASE TRANSMISSION" },
131         { NM_MT_BS11_CREATE_OBJ_NACK,   "BS11 CREATE OBJECT" },
132         { NM_MT_BS11_DELETE_OBJ_NACK,   "BS11 DELETE OBJECT" },
133         { 0,                            NULL }
134 };
135
136 const char *abis_nm_nack_name(uint8_t nack)
137 {
138         return get_value_string(nack_names, nack);
139 }
140
141 /* Chapter 9.4.36 */
142 static const struct value_string nack_cause_names[] = {
143         /* General Nack Causes */
144         { NM_NACK_INCORR_STRUCT,        "Incorrect message structure" },
145         { NM_NACK_MSGTYPE_INVAL,        "Invalid message type value" },
146         { NM_NACK_OBJCLASS_INVAL,       "Invalid Object class value" },
147         { NM_NACK_OBJCLASS_NOTSUPP,     "Object class not supported" },
148         { NM_NACK_BTSNR_UNKN,           "BTS no. unknown" },
149         { NM_NACK_TRXNR_UNKN,           "Baseband Transceiver no. unknown" },
150         { NM_NACK_OBJINST_UNKN,         "Object Instance unknown" },
151         { NM_NACK_ATTRID_INVAL,         "Invalid attribute identifier value" },
152         { NM_NACK_ATTRID_NOTSUPP,       "Attribute identifier not supported" },
153         { NM_NACK_PARAM_RANGE,          "Parameter value outside permitted range" },
154         { NM_NACK_ATTRLIST_INCONSISTENT,"Inconsistency in attribute list" },
155         { NM_NACK_SPEC_IMPL_NOTSUPP,    "Specified implementation not supported" },
156         { NM_NACK_CANT_PERFORM,         "Message cannot be performed" },
157         /* Specific Nack Causes */
158         { NM_NACK_RES_NOTIMPL,          "Resource not implemented" },
159         { NM_NACK_RES_NOTAVAIL,         "Resource not available" },
160         { NM_NACK_FREQ_NOTAVAIL,        "Frequency not available" },
161         { NM_NACK_TEST_NOTSUPP,         "Test not supported" },
162         { NM_NACK_CAPACITY_RESTR,       "Capacity restrictions" },
163         { NM_NACK_PHYSCFG_NOTPERFORM,   "Physical configuration cannot be performed" },
164         { NM_NACK_TEST_NOTINIT,         "Test not initiated" },
165         { NM_NACK_PHYSCFG_NOTRESTORE,   "Physical configuration cannot be restored" },
166         { NM_NACK_TEST_NOSUCH,          "No such test" },
167         { NM_NACK_TEST_NOSTOP,          "Test cannot be stopped" },
168         { NM_NACK_MSGINCONSIST_PHYSCFG, "Message inconsistent with physical configuration" },
169         { NM_NACK_FILE_INCOMPLETE,      "Complete file notreceived" },
170         { NM_NACK_FILE_NOTAVAIL,        "File not available at destination" },
171         { NM_NACK_FILE_NOTACTIVATE,     "File cannot be activate" },
172         { NM_NACK_REQ_NOT_GRANT,        "Request not granted" },
173         { NM_NACK_WAIT,                 "Wait" },
174         { NM_NACK_NOTH_REPORT_EXIST,    "Nothing reportable existing" },
175         { NM_NACK_MEAS_NOTSUPP,         "Measurement not supported" },
176         { NM_NACK_MEAS_NOTSTART,        "Measurement not started" },
177         { 0,                            NULL }
178 };
179
180 const char *abis_nm_nack_cause_name(uint8_t cause)
181 {
182         return get_value_string(nack_cause_names, cause);
183 }
184
185 /* Chapter 9.4.16: Event Type */
186 static const struct value_string event_type_names[] = {
187         { NM_EVT_COMM_FAIL,             "communication failure" },
188         { NM_EVT_QOS_FAIL,              "quality of service failure" },
189         { NM_EVT_PROC_FAIL,             "processing failure" },
190         { NM_EVT_EQUIP_FAIL,            "equipment failure" },
191         { NM_EVT_ENV_FAIL,              "environment failure" },
192         { 0,                            NULL }
193 };
194
195 const char *abis_nm_event_type_name(uint8_t cause)
196 {
197         return get_value_string(event_type_names, cause);
198 }
199
200 /* Chapter 9.4.63: Perceived Severity */
201 static const struct value_string severity_names[] = {
202         { NM_SEVER_CEASED,              "failure ceased" },
203         { NM_SEVER_CRITICAL,            "critical failure" },
204         { NM_SEVER_MAJOR,               "major failure" },
205         { NM_SEVER_MINOR,               "minor failure" },
206         { NM_SEVER_WARNING,             "warning level failure" },
207         { NM_SEVER_INDETERMINATE,       "indeterminate failure" },
208         { 0,                            NULL }
209 };
210
211 const char *abis_nm_severity_name(uint8_t cause)
212 {
213         return get_value_string(severity_names, cause);
214 }
215
216 /* Attributes that the BSC can set, not only get, according to Section 9.4 */
217 const enum abis_nm_attr abis_nm_att_settable[] = {
218         NM_ATT_ADD_INFO,
219         NM_ATT_ADD_TEXT,
220         NM_ATT_DEST,
221         NM_ATT_EVENT_TYPE,
222         NM_ATT_FILE_DATA,
223         NM_ATT_GET_ARI,
224         NM_ATT_HW_CONF_CHG,
225         NM_ATT_LIST_REQ_ATTR,
226         NM_ATT_MDROP_LINK,
227         NM_ATT_MDROP_NEXT,
228         NM_ATT_NACK_CAUSES,
229         NM_ATT_OUTST_ALARM,
230         NM_ATT_PHYS_CONF,
231         NM_ATT_PROB_CAUSE,
232         NM_ATT_RAD_SUBC,
233         NM_ATT_SOURCE,
234         NM_ATT_SPEC_PROB,
235         NM_ATT_START_TIME,
236         NM_ATT_TEST_DUR,
237         NM_ATT_TEST_NO,
238         NM_ATT_TEST_REPORT,
239         NM_ATT_WINDOW_SIZE,
240         NM_ATT_SEVERITY,
241         NM_ATT_MEAS_RES,
242         NM_ATT_MEAS_TYPE,
243 };
244
245 const struct tlv_definition abis_nm_att_tlvdef = {
246         .def = {
247                 [NM_ATT_ABIS_CHANNEL] =         { TLV_TYPE_FIXED, 3 },
248                 [NM_ATT_ADD_INFO] =             { TLV_TYPE_TL16V },
249                 [NM_ATT_ADD_TEXT] =             { TLV_TYPE_TL16V },
250                 [NM_ATT_ADM_STATE] =            { TLV_TYPE_TV },
251                 [NM_ATT_ARFCN_LIST]=            { TLV_TYPE_TL16V },
252                 [NM_ATT_AUTON_REPORT] =         { TLV_TYPE_TV },
253                 [NM_ATT_AVAIL_STATUS] =         { TLV_TYPE_TL16V },
254                 [NM_ATT_BCCH_ARFCN] =           { TLV_TYPE_FIXED, 2 },
255                 [NM_ATT_BSIC] =                 { TLV_TYPE_TV },
256                 [NM_ATT_BTS_AIR_TIMER] =        { TLV_TYPE_TV },
257                 [NM_ATT_CCCH_L_I_P] =           { TLV_TYPE_TV },
258                 [NM_ATT_CCCH_L_T] =             { TLV_TYPE_TV },
259                 [NM_ATT_CHAN_COMB] =            { TLV_TYPE_TV },
260                 [NM_ATT_CONN_FAIL_CRIT] =       { TLV_TYPE_TL16V },
261                 [NM_ATT_DEST] =                 { TLV_TYPE_TL16V },
262                 [NM_ATT_EVENT_TYPE] =           { TLV_TYPE_TV },
263                 [NM_ATT_FILE_DATA] =            { TLV_TYPE_TL16V },
264                 [NM_ATT_FILE_ID] =              { TLV_TYPE_TL16V },
265                 [NM_ATT_FILE_VERSION] =         { TLV_TYPE_TL16V },
266                 [NM_ATT_GSM_TIME] =             { TLV_TYPE_FIXED, 2 },
267                 [NM_ATT_HSN] =                  { TLV_TYPE_TV },
268                 [NM_ATT_HW_CONFIG] =            { TLV_TYPE_TL16V },
269                 [NM_ATT_HW_DESC] =              { TLV_TYPE_TL16V },
270                 [NM_ATT_INTAVE_PARAM] =         { TLV_TYPE_TV },
271                 [NM_ATT_INTERF_BOUND] =         { TLV_TYPE_FIXED, 6 },
272                 [NM_ATT_LIST_REQ_ATTR] =        { TLV_TYPE_TL16V },
273                 [NM_ATT_MAIO] =                 { TLV_TYPE_TV },
274                 [NM_ATT_MANUF_STATE] =          { TLV_TYPE_TV },
275                 [NM_ATT_MANUF_THRESH] =         { TLV_TYPE_TL16V },
276                 [NM_ATT_MANUF_ID] =             { TLV_TYPE_TL16V },
277                 [NM_ATT_MAX_TA] =               { TLV_TYPE_TV },
278                 [NM_ATT_MDROP_LINK] =           { TLV_TYPE_FIXED, 2 },
279                 [NM_ATT_MDROP_NEXT] =           { TLV_TYPE_FIXED, 2 },
280                 [NM_ATT_NACK_CAUSES] =          { TLV_TYPE_TV },
281                 [NM_ATT_NY1] =                  { TLV_TYPE_TV },
282                 [NM_ATT_OPER_STATE] =           { TLV_TYPE_TV },
283                 [NM_ATT_OVERL_PERIOD] =         { TLV_TYPE_TL16V },
284                 [NM_ATT_PHYS_CONF] =            { TLV_TYPE_TL16V },
285                 [NM_ATT_POWER_CLASS] =          { TLV_TYPE_TV },
286                 [NM_ATT_POWER_THRESH] =         { TLV_TYPE_FIXED, 3 },
287                 [NM_ATT_PROB_CAUSE] =           { TLV_TYPE_FIXED, 3 },
288                 [NM_ATT_RACH_B_THRESH] =        { TLV_TYPE_TV },
289                 [NM_ATT_LDAVG_SLOTS] =          { TLV_TYPE_FIXED, 2 },
290                 [NM_ATT_RAD_SUBC] =             { TLV_TYPE_TV },
291                 [NM_ATT_RF_MAXPOWR_R] =         { TLV_TYPE_TV },
292                 [NM_ATT_SITE_INPUTS] =          { TLV_TYPE_TL16V },
293                 [NM_ATT_SITE_OUTPUTS] =         { TLV_TYPE_TL16V },
294                 [NM_ATT_SOURCE] =               { TLV_TYPE_TL16V },
295                 [NM_ATT_SPEC_PROB] =            { TLV_TYPE_TV },
296                 [NM_ATT_START_TIME] =           { TLV_TYPE_FIXED, 2 },
297                 [NM_ATT_T200] =                 { TLV_TYPE_FIXED, 7 },
298                 [NM_ATT_TEI] =                  { TLV_TYPE_TV },
299                 [NM_ATT_TEST_DUR] =             { TLV_TYPE_FIXED, 2 },
300                 [NM_ATT_TEST_NO] =              { TLV_TYPE_TV },
301                 [NM_ATT_TEST_REPORT] =          { TLV_TYPE_TL16V },
302                 [NM_ATT_VSWR_THRESH] =          { TLV_TYPE_FIXED, 2 },
303                 [NM_ATT_WINDOW_SIZE] =          { TLV_TYPE_TV },
304                 [NM_ATT_TSC] =                  { TLV_TYPE_TV },
305                 [NM_ATT_SW_CONFIG] =            { TLV_TYPE_TL16V },
306                 [NM_ATT_SEVERITY] =             { TLV_TYPE_TV },
307                 [NM_ATT_GET_ARI] =              { TLV_TYPE_TL16V },
308                 [NM_ATT_HW_CONF_CHG] =          { TLV_TYPE_TL16V },
309                 [NM_ATT_OUTST_ALARM] =          { TLV_TYPE_TV },
310                 [NM_ATT_MEAS_RES] =             { TLV_TYPE_TL16V },
311         },
312 };
313
314 const struct value_string abis_nm_obj_class_names[] = {
315         { NM_OC_SITE_MANAGER,   "SITE-MANAGER" },
316         { NM_OC_BTS,            "BTS" },
317         { NM_OC_RADIO_CARRIER,  "RADIO-CARRIER" },
318         { NM_OC_BASEB_TRANSC,   "BASEBAND-TRANSCEIVER" },
319         { NM_OC_CHANNEL,        "CHANNEL" },
320         { NM_OC_BS11_ADJC,      "ADJC" },
321         { NM_OC_BS11_HANDOVER,  "HANDOVER" },
322         { NM_OC_BS11_PWR_CTRL,  "POWER-CONTROL" },
323         { NM_OC_BS11_BTSE,      "BTSE" },
324         { NM_OC_BS11_RACK,      "RACK" },
325         { NM_OC_BS11_TEST,      "TEST" },
326         { NM_OC_BS11_ENVABTSE,  "ENVABTSE" },
327         { NM_OC_BS11_BPORT,     "BPORT" },
328         { NM_OC_GPRS_NSE,       "GPRS-NSE" },
329         { NM_OC_GPRS_CELL,      "GPRS-CELL" },
330         { NM_OC_GPRS_NSVC,      "GPRS-NSVC" },
331         { NM_OC_BS11,           "SIEMENSHW" },
332         { 0,                    NULL }
333 };
334
335 const char *abis_nm_opstate_name(uint8_t os)
336 {
337         switch (os) {
338         case NM_OPSTATE_DISABLED:
339                 return "Disabled";
340         case NM_OPSTATE_ENABLED:
341                 return "Enabled";
342         case NM_OPSTATE_NULL:
343                 return "NULL";
344         default:
345                 return "RFU";
346         }
347 }
348
349 /* Chapter 9.4.7 */
350 static const struct value_string avail_names[] = {
351         { 0,    "In test" },
352         { 1,    "Failed" },
353         { 2,    "Power off" },
354         { 3,    "Off line" },
355         /* Not used */
356         { 5,    "Dependency" },
357         { 6,    "Degraded" },
358         { 7,    "Not installed" },
359         { 0xff, "OK" },
360         { 0,    NULL }
361 };
362
363 const char *abis_nm_avail_name(uint8_t avail)
364 {
365         return get_value_string(avail_names, avail);
366 }
367
368 static struct value_string test_names[] = {
369         /* FIXME: standard test names */
370         { NM_IPACC_TESTNO_CHAN_USAGE, "Channel Usage" },
371         { NM_IPACC_TESTNO_BCCH_CHAN_USAGE, "BCCH Channel Usage" },
372         { NM_IPACC_TESTNO_FREQ_SYNC, "Frequency Synchronization" },
373         { NM_IPACC_TESTNO_BCCH_INFO, "BCCH Info" },
374         { NM_IPACC_TESTNO_TX_BEACON, "Transmit Beacon" },
375         { NM_IPACC_TESTNO_SYSINFO_MONITOR, "System Info Monitor" },
376         { NM_IPACC_TESTNO_BCCCH_MONITOR, "BCCH Monitor" },
377         { 0, NULL }
378 };
379
380 const char *abis_nm_test_name(uint8_t test)
381 {
382         return get_value_string(test_names, test);
383 }
384
385 const struct value_string abis_nm_adm_state_names[] = {
386         { NM_STATE_LOCKED,      "Locked" },
387         { NM_STATE_UNLOCKED,    "Unlocked" },
388         { NM_STATE_SHUTDOWN,    "Shutdown" },
389         { NM_STATE_NULL,        "NULL" },
390         { 0, NULL }
391 };
392
393 void abis_nm_debugp_foh(int ss, struct abis_om_fom_hdr *foh)
394 {
395         DEBUGP(ss, "OC=%s(%02x) INST=(%02x,%02x,%02x) ",
396                 get_value_string(abis_nm_obj_class_names, foh->obj_class),
397                 foh->obj_class, foh->obj_inst.bts_nr, foh->obj_inst.trx_nr,
398                 foh->obj_inst.ts_nr);
399 }
400
401 static const enum abis_nm_chan_comb chcomb4pchan[] = {
402         [GSM_PCHAN_CCCH]        = NM_CHANC_mainBCCH,
403         [GSM_PCHAN_CCCH_SDCCH4] = NM_CHANC_BCCHComb,
404         [GSM_PCHAN_TCH_F]       = NM_CHANC_TCHFull,
405         [GSM_PCHAN_TCH_H]       = NM_CHANC_TCHHalf,
406         [GSM_PCHAN_SDCCH8_SACCH8C] = NM_CHANC_SDCCH,
407         [GSM_PCHAN_PDCH]        = NM_CHANC_IPAC_PDCH,
408         [GSM_PCHAN_TCH_F_PDCH]  = NM_CHANC_IPAC_TCHFull_PDCH,
409         /* FIXME: bounds check */
410 };
411
412 int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan)
413 {
414         if (pchan < ARRAY_SIZE(chcomb4pchan))
415                 return chcomb4pchan[pchan];
416
417         return -EINVAL;
418 }
419
420 enum abis_nm_chan_comb abis_nm_pchan4chcomb(uint8_t chcomb)
421 {
422         int i;
423         for (i = 0; i < ARRAY_SIZE(chcomb4pchan); i++) {
424                 if (chcomb4pchan[i] == chcomb)
425                         return i;
426         }
427         return GSM_PCHAN_NONE;
428 }