comparison gsm-fw/ccd/pdi.c @ 648:970d6199f2c5

gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Thu, 04 Sep 2014 05:48:57 +0000
parents
children
comparison
equal deleted inserted replaced
647:a60b375014e3 648:970d6199f2c5
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul : pdi.c
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose :
18 +-----------------------------------------------------------------------------
19 */
20
21 #define PDI_C
22
23 #include "typedefs.h"
24 #include "ccdapi.h"
25 #include "ccdtable.h"
26 #include "ccddata.h"
27 #include <malloc.h>
28 #include <memory.h>
29 #include <string.h>
30 #include "pdi.h"
31
32 #define GET_PD(m) ((m)->buf[((m)->o_buf)>>3] & 0x0f)
33 #define GET_TI(m) ((m)->buf[((m)->o_buf)>>3] >> 4)
34
35 /* Constants borrowed from grr.h */
36 #define CTRL_BLK_NO_OPT 1
37 #define CTRL_BLK_OPT 2
38
39 static T_PDI_DECODEINFO* g_DummyDecodeInfo = NULL;
40
41 static T_PDI_DECODEINFO m_def_dinfo[]={
42 /* type */ /* attrib */ /* prim */ /* entity */ /* mt */ /* pdi_prepare_ccdmsg */ /* primmbr */
43 {PDI_DECODETYPE_L3PDU_N, "sdu", "PH_*", "", 0xff, NULL, NULL},
44 {PDI_DECODETYPE_L3PDU_N, "sdu", "MPH_*", "", 0xff, NULL, NULL},
45 {PDI_DECODETYPE_L3PDU_N, "sdu", "DL_*", "", 0xff, NULL, NULL},
46 {PDI_DECODETYPE_L3PDU, "sdu", "XX_TAP*", "", 0xff, NULL, NULL},
47 {PDI_DECODETYPE_NOPD, "sdu", "XX_*", "XX", 0xff, NULL, NULL},
48 {PDI_DECODETYPE_L3PDU, "sdu", "*", "", 0xff, NULL, NULL}
49 };
50 #define DEF_DINFO_COUNT (sizeof(m_def_dinfo) / sizeof(*m_def_dinfo))
51
52 static UBYTE pdi_readmtype (T_MSGBUF* msg, UBYTE len)
53 {
54 UBYTE mt = msg->buf[msg->o_buf>>3] >> (8-len);
55 msg->l_buf -= len;
56 msg->o_buf += len;
57 return mt;
58 }
59
60 #define PDI_MBUFLEN 1024
61 static struct
62 {
63 U16 l_buf;
64 U16 o_buf;
65 char buf[PDI_MBUFLEN];
66 } pdi_msgbuf;
67
68 static int pdi_rmac_hdr (T_PDI_CCDMSG* ccdmsg, char* evalue, int evlen)
69 {
70 char* ptr_blk;
71 UBYTE payload, rrbp, sp;
72 evalue++; /* Assume it is an array and skip length delivered from ccdedit */
73 memcpy (pdi_msgbuf.buf, evalue, evlen > PDI_MBUFLEN ? PDI_MBUFLEN : evlen);
74 ptr_blk = evalue;
75 pdi_msgbuf.l_buf = evlen * 8;
76 pdi_msgbuf.o_buf = 0;
77 ccdmsg->mbuf = (T_MSGBUF*) &pdi_msgbuf;
78
79 /* the following is borrowed from grlc_gfff.c */
80 payload = (ptr_blk[0] & 0xC0) >> 6;
81 rrbp = (ptr_blk[0] & 0x30) >> 4;
82 sp = (ptr_blk[0] & 0x08) >> 3;
83
84 if (payload == CTRL_BLK_NO_OPT)
85 {
86 /* msg starts at byte #2 */
87 pdi_msgbuf.l_buf -= 8;
88 pdi_msgbuf.o_buf += 8;
89 }
90 else if ((payload == CTRL_BLK_OPT) &&
91 !(ptr_blk[1] & 0x01) &&
92 !(ptr_blk[1] & 0x80) &&
93 (ptr_blk[1] & 0x02))
94 {
95 /* msg starts at byte #3 */
96 pdi_msgbuf.l_buf -= 16;
97 pdi_msgbuf.o_buf += 16;
98 }
99 else if ((payload == CTRL_BLK_OPT) &&
100 (ptr_blk[1] & 0x01) &&
101 !(ptr_blk[1] & 0x80) &&
102 (ptr_blk[1] & 0x02))
103 {
104 /* msg starts at byte #4 */
105 pdi_msgbuf.l_buf -= 24;
106 pdi_msgbuf.o_buf += 24;
107 }
108 else
109 {
110 return PDI_NONE;
111 }
112 return PDI_CCDMSG;
113 }
114
115 T_PDI_CONTEXT* CCDDATA_PREF(pdi_createDefContext)()
116 {
117 const T_PDI_DECODEINFO* dinfo;
118 int dinfo_count=ccddata_get_pdi_dinfo(&dinfo);
119 if (dinfo_count==0)
120 {
121 dinfo_count=DEF_DINFO_COUNT;
122 dinfo=m_def_dinfo;
123 }
124 return CCDDATA_PREF(pdi_createContext)(dinfo,dinfo_count);
125 }
126
127
128 T_PDI_CONTEXT* CCDDATA_PREF(pdi_createContext)(const T_PDI_DECODEINFO *dinfo, unsigned int dicount)
129 {
130 int i;
131 USHORT sap, opc, dir, di;
132 USHORT pmtx;
133 T_PDI_DECODEINFO* decodeInfo[1024];
134 int decodeInfoCount;
135 int len;
136
137 T_PDI_CONTEXT *context;
138
139 if (context = (T_PDI_CONTEXT*)malloc(sizeof(T_PDI_CONTEXT)))
140 {
141 // copy dinfo
142 if (!(context->dinfo = (T_PDI_DECODEINFO*)malloc(sizeof(T_PDI_DECODEINFO)*dicount)))
143 {
144 free(context);
145 return NULL;
146 }
147 memcpy(context->dinfo, dinfo, sizeof(T_PDI_DECODEINFO)*dicount);
148
149 // PD -> CCDENT
150 memset(context->PdEntityTable, -1, sizeof(T_PDI_PdEntityTable));
151 context->PdEntityTable[PD_XX] = ccddata_get_ccdent("XX");
152 context->PdEntityTable[PD_CC] = ccddata_get_ccdent("CC");
153 context->PdEntityTable[PD_MM] = ccddata_get_ccdent("MM");
154 context->PdEntityTable[PD_RR] = ccddata_get_ccdent("RR");
155 context->PdEntityTable[PD_GMM] = ccddata_get_ccdent("GMM");
156 context->PdEntityTable[PD_SMS] = ccddata_get_ccdent("SMS");
157 context->PdEntityTable[PD_SS] = ccddata_get_ccdent("SS");
158 context->PdEntityTable[PD_SM] = ccddata_get_ccdent("SM");
159 context->PdEntityTable[PD_TST] = ccddata_get_ccdent("TST");
160
161 /* initialize mi_length */
162 context->mi_length = ccddata_get_mi_length ();
163
164 // count pcomp
165 i = 0;
166 while (ccddata_get_pcomp((USHORT)i)->name != NULL) i++;
167 context->PrimDecodeInfo = (T_PDI_DECODEINFO***)malloc(i*sizeof(T_PDI_DECODEINFO**));
168 memset(context->PrimDecodeInfo, 0, i*sizeof(int*));
169
170 // search all primitives
171 for (sap = 0; sap <= ccddata_get_max_sap_num(); sap++)
172 for (opc = 0; opc <= (USHORT)ccddata_get_max_primitive_id(); opc++)
173 for (dir = 0; dir <= 1; dir++)
174 if ((pmtx = ccddata_get_pmtx(sap, opc, dir)) != NO_REF)
175 {
176 const char* pname;
177 pname = ccddata_get_pcomp(pmtx)->name;
178
179 decodeInfoCount = 0;
180 for (di = 0; di < dicount; di++)
181 {
182 int wildcard;
183 len = strlen(context->dinfo[di].prim);
184 if (context->dinfo[di].prim[len-1] == '*')
185 {
186 wildcard = 1;
187 len--;
188 }
189 else
190 {
191 wildcard = 0;
192 len = strlen(pname);
193 }
194
195 if (wildcard)
196 {
197 if (!strncmp(context->dinfo[di].prim, pname, len))
198 {
199 decodeInfo[decodeInfoCount] = &context->dinfo[di];
200 decodeInfoCount++;
201 }
202 }
203 else
204 {
205 if (!strcmp(context->dinfo[di].prim, pname))
206 {
207 decodeInfo[decodeInfoCount] = &context->dinfo[di];
208 decodeInfoCount++;
209 }
210 }
211 }
212
213 // store decodeInfo for this primitive
214 if (decodeInfoCount != 0)
215 {
216 decodeInfo[decodeInfoCount] = g_DummyDecodeInfo;
217 decodeInfoCount++;
218 context->PrimDecodeInfo[pmtx] = (T_PDI_DECODEINFO**)
219 malloc(decodeInfoCount*sizeof(T_PDI_DECODEINFO*));
220 if (context->PrimDecodeInfo+pmtx)
221 {
222 memcpy(context->PrimDecodeInfo[pmtx], &decodeInfo,
223 decodeInfoCount*sizeof(T_PDI_DECODEINFO*));
224
225 }
226 else
227 context->PrimDecodeInfo[pmtx] = &g_DummyDecodeInfo;
228 }
229 else
230 context->PrimDecodeInfo[pmtx] = &g_DummyDecodeInfo;
231
232 } // endif (pmtx != NO_REF)
233 }
234
235 return context;
236 }
237
238
239
240 void CCDDATA_PREF(pdi_destroyContext)(T_PDI_CONTEXT *context)
241 {
242 int i = 0;
243
244 if (context==NULL) return;
245
246 while (ccddata_get_pcomp((USHORT)i)->name != NULL)
247 {
248 if ((context->PrimDecodeInfo[i] != NULL) &&
249 (context->PrimDecodeInfo[i][0] != NULL))
250 free(context->PrimDecodeInfo[i]);
251 i++;
252 }
253 if (context->PrimDecodeInfo != NULL)
254 free(context->PrimDecodeInfo);
255
256 free(context->dinfo);
257
258 free(context);
259 }
260
261
262
263 void CCDDATA_PREF(pdi_startPrim)(T_PDI_CONTEXT *context, ULONG opc)
264 {
265 context->sapi = 0;
266
267 if (opc & 0x80000000)
268 {
269 context->sap = (USHORT) (opc & 0x3fff);
270 context->opc = (USHORT) ((opc >> 16) & 0xff);
271 }
272 else
273 {
274 context->sap = (USHORT) (((opc & 0x3f00)>>8) & 0xff);
275 context->opc = (USHORT) (opc & 0xff);
276 }
277 context->dir = (UBYTE) (((opc & 0x4000)>>14) & 0x01);
278
279 context->pmtx = ccddata_get_pmtx(context->sap, context->opc, context->dir);
280 context->mtypenum = 0;
281 }
282
283 void CCDDATA_PREF(pdi_getDecodeInfo)(T_PDI_CONTEXT *context, const char *ename,
284 char *evalue, int evlen, T_PDI *decinfo)
285 {
286 int i=0;
287 T_PDI_DECODEINFO* di;
288
289 decinfo->decodetype = PDI_NONE;
290
291 while (di = context->PrimDecodeInfo[context->pmtx][i++])
292 {
293 if ((di->type == PDI_DECODETYPE_SAPI) && (strcmp(ename, "sapi") == 0))
294 {
295 context->sapi = evalue[0];
296 }
297
298 if (!strcmp(ename, di->attrib))
299 {
300 decinfo->pdi.ccdmsg.msg_type = 0xff;
301
302 if (di->pdi_prepare_ccdmsg)
303 {
304 decinfo->decodetype = (*di->pdi_prepare_ccdmsg)
305 (&decinfo->pdi.ccdmsg, context->mtypeval,
306 context->mtypenum);
307 if (decinfo->decodetype == PDI_NONE)
308 {
309 continue;
310 }
311 }
312
313 switch (di->type)
314 {
315 case PDI_DECODETYPE_AIM:
316 case PDI_DECODETYPE_AIM_N:
317 case PDI_DECODETYPE_AIM_CHECK:
318 case PDI_DECODETYPE_AIM_N_CHECK:
319 decinfo->decodetype = PDI_CCDMSG;
320 memcpy (pdi_msgbuf.buf, evalue,
321 evlen > PDI_MBUFLEN ? PDI_MBUFLEN : evlen);
322 pdi_msgbuf.l_buf = evlen * 8;
323 pdi_msgbuf.o_buf = 0;
324
325 /* first byte: don't care */
326 pdi_msgbuf.l_buf -= 8;
327 pdi_msgbuf.o_buf += 8;
328 decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*) &pdi_msgbuf;
329 decinfo->pdi.ccdmsg.pd = GET_PD (decinfo->pdi.ccdmsg.mbuf);
330 if (strcmp (di->entity,
331 CCDDATA_PREF(pdi_pd2name)(decinfo->pdi.ccdmsg.pd)))
332 {
333 /* pd does not match the configured entity */
334 decinfo->decodetype = PDI_CCDMSG;
335 continue;
336 }
337 else
338 {
339 pdi_msgbuf.l_buf -= 8;
340 pdi_msgbuf.o_buf += 8;
341 }
342 //decinfo->pdi.ccdmsg.ti = GET_TI (decinfo->pdi.ccdmsg.mbuf);
343 decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_AIM) ||
344 (di->type == PDI_DECODETYPE_AIM_CHECK) ?
345 context->dir : (~context->dir)&1;
346 decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity);
347 decinfo->pdi.ccdmsg.msg_type = pdi_readmtype (
348 decinfo->pdi.ccdmsg.mbuf,
349 context->mi_length[decinfo->pdi.ccdmsg.entity]);
350 break;
351 case PDI_DECODETYPE_L3PDU_N:
352 case PDI_DECODETYPE_L3PDU:
353 decinfo->decodetype = PDI_CCDMSG;
354
355 decinfo->pdi.ccdmsg.pd = GET_PD ((T_MSGBUF*) evalue);
356 decinfo->pdi.ccdmsg.ti = GET_TI ((T_MSGBUF*) evalue);
357 decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_L3PDU) ?
358 context->dir : (~context->dir)&1;
359
360 decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue;
361
362 if (CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd)==-1)
363 {
364 decinfo->decodetype = PDI_NONE;
365 }
366 else
367 {
368 decinfo->pdi.ccdmsg.entity = (UBYTE)CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd);
369
370 ((T_MSGBUF*)evalue)->o_buf += 8;
371 ((T_MSGBUF*)evalue)->l_buf -= 8;
372
373 decinfo->pdi.ccdmsg.msg_type = pdi_readmtype ((T_MSGBUF*)evalue,
374 context->mi_length[decinfo->pdi.ccdmsg.entity]);
375 }
376
377 /* remove SSN bit */
378 if (!strcmp ("DL_DATA_REQ", ccddata_get_pcomp (context->pmtx)->name))
379 {
380 if (decinfo->pdi.ccdmsg.pd == PD_CC ||
381 decinfo->pdi.ccdmsg.pd == PD_MM ||
382 decinfo->pdi.ccdmsg.pd == PD_SS)
383 {
384 decinfo->pdi.ccdmsg.msg_type &= ~0x40;
385 }
386 }
387 break;
388
389 case PDI_DECODETYPE_NOPD:
390 case PDI_DECODETYPE_NOPD_N:
391 case PDI_DECODETYPE_RR_SHORT:
392 decinfo->decodetype = PDI_CCDMSG;
393
394 decinfo->pdi.ccdmsg.pd = 0;
395 decinfo->pdi.ccdmsg.ti = 0;
396 decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_NOPD) ?
397 context->dir : (~context->dir)&1;
398
399 decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue;
400 decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity);
401 decinfo->pdi.ccdmsg.msg_type = pdi_readmtype ((T_MSGBUF*)evalue,
402 context->mi_length[decinfo->pdi.ccdmsg.entity]);
403 break;
404
405 case PDI_DECODETYPE_NOPD_NOTYPE:
406 case PDI_DECODETYPE_NOPD_NOTYPE_N:
407 decinfo->decodetype = PDI_CCDMSG;
408
409 decinfo->pdi.ccdmsg.pd = 0;
410 decinfo->pdi.ccdmsg.ti = 0;
411 decinfo->pdi.ccdmsg.dir = (di->type == PDI_DECODETYPE_NOPD_NOTYPE) ?
412 context->dir : (~context->dir)&1;
413
414 decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue;
415
416 if (decinfo->pdi.ccdmsg.msg_type == 0xff)
417 {
418 decinfo->pdi.ccdmsg.msg_type = di->msg_type;
419 }
420
421 decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity);
422 break;
423
424 case PDI_DECODETYPE_MAC_H:
425 case PDI_DECODETYPE_MAC_H_N:
426 case PDI_DECODETYPE_MAC_H_CHECK:
427 case PDI_DECODETYPE_MAC_H_N_CHECK:
428 if ((decinfo->decodetype = pdi_rmac_hdr (&decinfo->pdi.ccdmsg,
429 evalue, evlen)) == PDI_CCDMSG)
430 {
431 decinfo->pdi.ccdmsg.pd = 0;
432 decinfo->pdi.ccdmsg.ti = 0;
433 decinfo->pdi.ccdmsg.dir = ((di->type == PDI_DECODETYPE_MAC_H) ||
434 (di->type == PDI_DECODETYPE_MAC_H_CHECK))
435 ? context->dir : (~context->dir)&1;
436 decinfo->pdi.ccdmsg.entity = (UBYTE)ccddata_get_ccdent(di->entity);
437 decinfo->pdi.ccdmsg.msg_type =
438 pdi_readmtype (decinfo->pdi.ccdmsg.mbuf,
439 context->mi_length[decinfo->pdi.ccdmsg.entity]);
440 }
441 break;
442
443 case PDI_DECODETYPE_SAPI:
444 decinfo->decodetype = PDI_NONE;
445 if (context->sapi == 1) // only sapi1 (GMM) has data for ccd
446 {
447 decinfo->decodetype = PDI_CCDMSG;
448
449 decinfo->pdi.ccdmsg.pd = GET_PD ((T_MSGBUF*) evalue);
450 decinfo->pdi.ccdmsg.ti = GET_TI ((T_MSGBUF*) evalue);
451 decinfo->pdi.ccdmsg.dir = context->dir;
452
453 /* !!! TBD !!! */
454 /* find msg_type*/
455 /* !!! TBD !!! */
456
457 decinfo->pdi.ccdmsg.mbuf = (T_MSGBUF*)evalue;
458
459 ((T_MSGBUF*)evalue)->o_buf += 8;
460 ((T_MSGBUF*)evalue)->l_buf -= 8;
461
462 if (CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd)==-1)
463 {
464 decinfo->decodetype = PDI_NONE;
465 }
466 else
467 {
468 decinfo->pdi.ccdmsg.entity = (UBYTE)CCDDATA_PREF(pdi_getEntityByPD)(context, decinfo->pdi.ccdmsg.pd);
469 }
470 }
471 break;
472
473 default:
474 decinfo->decodetype = PDI_NONE;
475 }
476
477 break;
478 } /* endif (strcmp) */
479 else
480 {
481 if (evlen > 4 || evlen < 0 || evlen == 3)
482 {
483 /* don't check prim members for non base types */
484 continue;
485 }
486 /* check for prim members later needed for finding out msg type */
487 if (di->primmbr)
488 {
489 int i;
490 for (i=0; di->primmbr[i] && context->mtypenum<PDI_MAXPMEMFORMTYPE; i++)
491 {
492 if (!strcmp(ename, di->primmbr[i]))
493 {
494 switch (evlen)
495 {
496 case 1:
497 context->mtypeval[context->mtypenum++] =
498 (ULONG) * (UBYTE*) evalue;
499 break;
500 case 2:
501 context->mtypeval[context->mtypenum++] =
502 (ULONG) * (USHORT*) evalue;
503 break;
504 case 4:
505 default:
506 context->mtypeval[context->mtypenum++] = * (ULONG*) evalue;
507 break;
508 }
509 }
510 }
511 }
512 }
513 } /* endwhile */
514
515 }
516
517 short CCDDATA_PREF(pdi_getEntityByPD)(const T_PDI_CONTEXT *context, unsigned char pd)
518 {
519 if ((pd > 16) || (context->PdEntityTable == NULL))
520 return -1;
521 else
522 return context->PdEntityTable[pd];
523 }
524
525
526 const char* CCDDATA_PREF(pdi_pd2name)(unsigned char pd)
527 {
528 switch (pd) {
529 case PD_XX: return "XX";
530 case PD_CC: return "CC";
531 case PD_MM: return "MM";
532 case PD_RR: return "RR";
533 case PD_GMM: return "GMM";
534 case PD_SMS: return "SMS";
535 case PD_SS: return "SS";
536 case PD_SM: return "SM";
537 case PD_TST: return "TST";
538
539 default: return "??";
540 }
541 }