2290 lines
49 KiB
C
2290 lines
49 KiB
C
#include "common.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "id_list.h"
|
|
#include "gsm_desc.h"
|
|
|
|
#define OUTF(a...) do { \
|
|
printf(" %3d: %02x ", (int)(data - start), data[0]); \
|
|
printf(a); \
|
|
} while (0)
|
|
|
|
#define OUT(a...) do { \
|
|
printf(a); \
|
|
} while (0)
|
|
|
|
#define RETTRUNK() do { \
|
|
printf("%s:%d TRUNKATED (0x%p - 0x%p)\n", __func__, __LINE__, data, end); \
|
|
return; \
|
|
} while (0)
|
|
|
|
static void l2_rrm();
|
|
static void l2_sms();
|
|
static void l2_cc();
|
|
static void l2_RRsystemInfo1();
|
|
static void l2_MccMncLac();
|
|
static void l2_RRsystemInfo2();
|
|
//static void l2_RRsystemInfo2ter();
|
|
static void l2_RRsystemInfo3C();
|
|
static void l2_RRsystemInfo4C();
|
|
static void l2_RRsystemInfo6();
|
|
static void l2_RRsystemInfo13C();
|
|
static void l2_RRimmediateAssTBFC();
|
|
static void l2_RRassignCommand();
|
|
static void l2_RRassignComplete();
|
|
static void l2_RRpagingrequest1();
|
|
static void l2_RRpagingrequest2();
|
|
static void l2_RRpagingrequest3();
|
|
static void l2_RRimmediateAssignment();
|
|
static void l2_RRimmAssTBFDirEncHoChaC();
|
|
static void l2_MobId();
|
|
static void l2_mmm();
|
|
static void l2_HoppingChannel();
|
|
static void l2_SingleChannel();
|
|
static void l2_HoppingChannelAssCom();
|
|
static void l2_SingleChannelAssCom();
|
|
static void l2_MobileAllocation();
|
|
static void l2_BcchAllocation();
|
|
static void l2_TmsiReallocCommand();
|
|
static void l2_RachControlParameters();
|
|
static void l2_bcc();
|
|
static void l2_Bbis();
|
|
static void l2_ChannelRelease();
|
|
static void l2_MMcmServiceRequest();
|
|
static void l2_RRciphModCmd();
|
|
static void l2_RRciphModCompl();
|
|
static void l2_RRpagingresponse();
|
|
static void l2_RRclassmarkChange();
|
|
|
|
static void l2_ChannelNeeded(char *str, unsigned char ch);
|
|
static void l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c);
|
|
|
|
static char *BitRow(unsigned char c, int pos);
|
|
static char *PageMode(unsigned char mode);
|
|
static char *BitRowFill(unsigned char c, unsigned char mask);
|
|
|
|
static void dcch_address();
|
|
static void dcch_control();
|
|
static void ControlChannelDescription();
|
|
static void CellOptionsBcch();
|
|
static void CellSelectionParameters();
|
|
static void RequestReference();
|
|
static void TimingAdvance();
|
|
static void StartingTime();
|
|
static void l2_NeighbourCellDescription();
|
|
static void CellIdentity();
|
|
static void MSClassMarkTwo();
|
|
static void cpData();
|
|
static void Address(const char *str);
|
|
static void ChannelDescriptionTwo();
|
|
static void CCalerting();
|
|
static void CCsetup();
|
|
static void ProgressIndicator();
|
|
static void Cause();
|
|
static void SmsProtocolDataValidity();
|
|
static void BearerCap();
|
|
static void AuthenticationRequest();
|
|
static void AuthenticationResponse();
|
|
|
|
static const unsigned char *start;
|
|
static const unsigned char *data;
|
|
static const unsigned char *end;
|
|
|
|
/*
|
|
* B-format (and also A-Format)
|
|
*/
|
|
void
|
|
l2_data_out_B(int fn, const unsigned char *input_data, int len)
|
|
{
|
|
data = input_data;
|
|
start = data;
|
|
end = data + len;
|
|
HEXDUMPF(data, 23 /*len*/, "Format B DATA\n");
|
|
/* Need at least 3 octets */
|
|
if (data + 2 >= end)
|
|
RETTRUNK();
|
|
|
|
dcch_address();
|
|
data++;
|
|
dcch_control();
|
|
data++;
|
|
/* FIXME: Why is extended length always set to 1? */
|
|
OUTF("%s EL, Extended Length: %s\n", BitRow(data[0], 0), (data[0] & 1)?"y":"n");
|
|
OUTF("%s M, segmentation: %c\n", BitRow(data[0], 1), ((data[0] >> 1) & 1)?'Y':'N');
|
|
OUTF("%s Length: %u\n", BitRowFill(data[0], 0xfc), data[0] >> 2);
|
|
if (data + (data[0] >> 2) < end)
|
|
end = data + (data[0] >> 2) + 1;
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
l2_Bbis();
|
|
}
|
|
|
|
static void
|
|
dcch_control()
|
|
{
|
|
if ((data[0] & 0x03) != 3)
|
|
{
|
|
if ((data[0] & 1) == 0)
|
|
{
|
|
OUTF("-------0 Information Frame\n");
|
|
OUTF("%s N(S), Sequence counter: %u\n", BitRowFill(data[0], 0x0e), (data[0] >> 1) & 0x07);
|
|
OUTF("%s P\n", BitRow(data[0], 4));
|
|
} else if ((data[0] & 0x03) == 1) {
|
|
OUTF("------01 Supvervisory Frame\n");
|
|
if (((data[0] >> 2) & 0x03) == 0)
|
|
OUTF("----00-- RR Frame (Receive ready)\n");
|
|
else if (((data[0] >> 2) & 0x03) == 1)
|
|
OUTF("----01-- RNR Frame (Receive not ready)\n");
|
|
else if (((data[0] >> 2) & 0x03) == 2)
|
|
OUTF("----10-- REJ Frame (REJect)\n");
|
|
else
|
|
OUTF("----11-- UNKNOWN\n");
|
|
OUTF("%s Poll/Final bit (P/F)\n", BitRow(data[0], 4));
|
|
}
|
|
OUTF("%s N(R), Retransmission counter: %u\n", BitRowFill(data[0], 0xe0), (data[0] >> 5) & 0x07);
|
|
return;
|
|
}
|
|
OUTF("------11 Unnumbered Frame\n");
|
|
switch (data[0] & 0xec) /* 11101100 */
|
|
{
|
|
case 0x6c: /* 011-11-- */
|
|
OUTF("%s P\n", BitRow(data[0], 4));
|
|
OUTF("011-11-- SABM frame (Set asynchonous balance mode)\n");
|
|
break;
|
|
case 0x0c: /* 000-11-- */
|
|
OUTF("%s F\n", BitRow(data[0], 4));
|
|
OUTF("000-11-- DM frame (Disconnected mode)\n");
|
|
break;
|
|
case 0x00:
|
|
OUTF("%s P\n", BitRow(data[0], 4));
|
|
OUTF("000-00-- UI frame (Unnumbered information)\n");
|
|
break;
|
|
case 0x40:
|
|
OUTF("%s P\n", BitRow(data[0], 4));
|
|
OUTF("010-00-- DISC frame (DISConnect)\n");
|
|
break;
|
|
case 0x60:
|
|
OUTF("%s P\n", BitRow(data[0], 4));
|
|
OUTF("011-00-- UA frame (Unnumbered achknowledgement)\n");
|
|
break;
|
|
default:
|
|
OUTF("%s P/F\n", BitRow(data[0], 4));
|
|
OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xec));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
dcch_address()
|
|
{
|
|
if (data[0] & 1)
|
|
OUTF("-------1 Extended Address: 1 octet long\n");
|
|
else
|
|
OUTF("-------0 Extended Address: more octets follow\n");
|
|
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- C/R: Command\n");
|
|
else
|
|
OUTF("------0- C/R: Response\n");
|
|
|
|
if (data[0] & 1)
|
|
{
|
|
/* SAPI */
|
|
switch ((data[0] >> 2) & 0x07)
|
|
{
|
|
case 0x03:
|
|
OUTF("---011-- SAPI: SMS and SS\n");
|
|
break;
|
|
case 0x00:
|
|
OUTF("---000-- SAPI: RR, MM and CC\n");
|
|
break;
|
|
default:
|
|
OUTF("%s SAPI: UNKNWON\n", BitRowFill(data[0], 0x1c));
|
|
break;
|
|
}
|
|
|
|
switch ((data[0] >> 4 ) & 0x03)
|
|
{
|
|
case 0x00:
|
|
OUTF("%s Link Protocol Disciminator: GSM (not Cell Broadcasting)\n", BitRowFill(data[0], 0x60));
|
|
break;
|
|
case 0x01:
|
|
OUTF("%s Link Protocol Disciminator: Cell Broadcasting (CBS)\n", BitRowFill(data[0], 0x60));
|
|
break;
|
|
default:
|
|
OUTF("%s Link Protocol Disciminator: UNKNOWN %u\n", BitRowFill(data[0], 0x60), (data[0] >> 5) & 0x03);
|
|
}
|
|
} else {
|
|
switch ((data[0] >> 2))
|
|
{
|
|
case 0x03:
|
|
OUTF("000011-- SAPI: SMS and SS\n");
|
|
break;
|
|
case 0x00:
|
|
OUTF("000000-- SAPI: RR, MM and CC\n");
|
|
break;
|
|
default:
|
|
OUTF("%s SAPI: UNKNOWN\n", BitRowFill(data[0], 0xfc));
|
|
break;
|
|
}
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] & 1)
|
|
OUTF("-------1 Extended Address: 1 octet long\n");
|
|
else
|
|
OUTF("-------0 Extended Address: more octets follow [ERROR]\n");
|
|
OUTF("%s Terminal Endpoint Identifier (TEI): %u\n", BitRowFill(data[0], 0xfe), data[0] >> 1);
|
|
}
|
|
}
|
|
|
|
void
|
|
l2_data_out_Bbis(int fn, const unsigned char *input_data, int len)
|
|
{
|
|
int i;
|
|
|
|
|
|
if (len <= 0)
|
|
return;
|
|
|
|
data = input_data;
|
|
start = data;
|
|
|
|
i = data[0] >> 2;
|
|
if (len - 1 < i)
|
|
OUTF("WARN: packet to short\n");
|
|
len = MIN(len - 1, i);
|
|
/* len = number of octets following the length field */
|
|
end = data + len + 1;
|
|
|
|
HEXDUMPF(data, 23 /*len*/, "Format Bbis DATA\n");
|
|
if (len <= 0)
|
|
return;
|
|
|
|
OUTF("%s Pseudo Length: %d\n", BitRowFill(data[0], 0xfc), data[0] >> 2);
|
|
data++;
|
|
l2_Bbis();
|
|
}
|
|
|
|
static void
|
|
l2_Bbis()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
switch (data[0] >> 7)
|
|
{
|
|
case 1:
|
|
OUTF("1------- Direction: To originating site\n");
|
|
break;
|
|
default:
|
|
OUTF("0------- Direction: From originating site\n");
|
|
}
|
|
|
|
OUTF("%s %d TransactionID\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 7);
|
|
|
|
switch (data[0] & 0x0f)
|
|
{
|
|
case 0:
|
|
OUTF("----0000 Group Call Control [FIXME]\n");
|
|
break;
|
|
case 1:
|
|
OUTF("----0001 Broadcast call control [FIXME]\n");
|
|
data++;
|
|
l2_bcc();
|
|
/* TS GSM 04.69 */
|
|
break;
|
|
case 2:
|
|
OUTF("----0010 PDSS1 [FIXME]\n");
|
|
break;
|
|
case 3:
|
|
OUTF("----0011 Call control. call related SS messages\n");
|
|
data++;
|
|
l2_cc();
|
|
/* TS 24.008 */
|
|
break;
|
|
case 4:
|
|
OUTF("----01-- PDSS2 [FIXME]\n");
|
|
break;
|
|
case 5:
|
|
OUTF("----0101 Mobile Management Message (non GPRS)\n");
|
|
data++;
|
|
/* TS 24.008 */
|
|
l2_mmm();
|
|
break;
|
|
case 6:
|
|
OUTF("----0110 Radio Resouce Management\n");
|
|
data++;
|
|
l2_rrm();
|
|
break;
|
|
case 7:
|
|
OUTF("----0111 RFU [FIXME]\n");
|
|
break;
|
|
case 8:
|
|
OUTF("----1000 GPRS Mobile Management\n");
|
|
/* in GMMattachAccept */
|
|
/* in GMMidentityRequest */
|
|
OUTF("FIXME: possible IMEI in here\n");
|
|
break;
|
|
case 9:
|
|
OUTF("----1001 SMS messages\n");
|
|
data++;
|
|
l2_sms();
|
|
/* TS 04.11 */
|
|
break;
|
|
case 0x0a:
|
|
OUTF("----1011 GRPS session management messages [FIXME]\n");
|
|
break;
|
|
case 0x0b:
|
|
OUTF("----1011 Non-call related SS messages [FIXME]\n");
|
|
/* GSM 04.80 */
|
|
break;
|
|
case 0x0c:
|
|
OUTF("----1100 Location services [FIXME]\n");
|
|
break;
|
|
case 0x0d:
|
|
OUTF("----1101 RFU [FIXME]\n");
|
|
break;
|
|
case 0x0e:
|
|
OUTF("----1110 Extension of the PD to one octet length [FIXME]\n");
|
|
break;
|
|
case 0x0f:
|
|
OUTF("----1111 Tests procedures describe in TS GSM 11.10 [FIXME]\n");
|
|
break;
|
|
default:
|
|
OUTF("%s 0x%02x UNKNOWN\n", BitRowFill(data[0], 0x0f), data[0] & 0x0f);
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* Broadcast Call Control (04.69)
|
|
*/
|
|
static void
|
|
l2_bcc()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
/* Message type 04.69:9.3*/
|
|
switch (data[0] & 0x3f)
|
|
{
|
|
case 0x06: /* 0-000110 */
|
|
OUTF("--000110 ???\n");
|
|
break;
|
|
default:
|
|
OUTF("--?????? UNKNOWN [FIXME]\n");
|
|
return;
|
|
}
|
|
|
|
/* Call reference 04.69:9.4.1*/
|
|
|
|
/* Orig indication 04.69:9.5.5*/
|
|
/* Spare half octet 04.69:9.4.5*/
|
|
|
|
}
|
|
|
|
/*
|
|
* ProtDisc3
|
|
*/
|
|
static void
|
|
l2_cc()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Send Sequence Number: %u\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
|
|
|
|
if ((data[0] & 0x3f) == 0x01)
|
|
{
|
|
OUTF("--000001 Call Alerting\n");
|
|
data++;
|
|
CCalerting();
|
|
} else if ((data[0] & 0x3f) == 0x02) {
|
|
OUTF("--000010 Call Proceesing\n");
|
|
if (++data >= end)
|
|
return;
|
|
OUTF("FIXME %s\n", __func__);
|
|
} else if ((data[0] & 0x3f) == 0x07) {
|
|
OUTF("--000111 Call Connect\n");
|
|
if (++data >= end)
|
|
return;
|
|
OUTF("FIXME %s\n", __func__);
|
|
} else if ((data[0] & 0x3f) == 0x08) {
|
|
OUTF("--001000 Call Confirmed\n");
|
|
if (++data >= end)
|
|
return;
|
|
if (data[0] != 0x04)
|
|
return;
|
|
OUTF("--000010 Bearer Capability\n");
|
|
data++;
|
|
BearerCap();
|
|
} else if ((data[0] & 0x3f) == 0x05) {
|
|
OUTF("--000101 Call Setup\n");
|
|
data++;
|
|
CCsetup();
|
|
} else if ((data[0] & 0x3f) == 0x03) {
|
|
OUTF("--000011 Call Progress\n");
|
|
data++;
|
|
ProgressIndicator();
|
|
} else if ((data[0] & 0x3f) == 0x0f) {
|
|
OUTF("--001111 Connect Acknowledge\n");
|
|
} else if ((data[0] & 0x3f) == 0x25) {
|
|
OUTF("--100101 Disconnect\n");
|
|
data++;
|
|
Cause();
|
|
} else if ((data[0] & 0x3f) == 0x2d) {
|
|
OUTF("--101101 CC Release\n");
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
if (data[0] == 0x08)
|
|
{
|
|
data++;
|
|
Cause();
|
|
}
|
|
} else if ((data[0] & 0x3f) == 0x2a) {
|
|
OUTF("--101010 CC Release Complete\n");
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
if (data[0] == 0x08)
|
|
{
|
|
data++;
|
|
Cause();
|
|
}
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] == 0x1c)
|
|
{
|
|
/* facility */
|
|
OUTF("FIXME\n");
|
|
}
|
|
} else {
|
|
OUTF("%s FIXME %s\n", BitRowFill(data[0], 0xff), __func__);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ----0101
|
|
* ProtDisc5 - Mobile Management message (non GPRS)
|
|
*/
|
|
static void
|
|
l2_mmm()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
OUTF("%s SendSequenceNumber: %d\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
|
|
switch (data[0] & 0x3f)
|
|
{
|
|
case 1:
|
|
//l2_MMimsiDetIndication(data + 1, end);
|
|
OUTF("--000001 Imsi Det Indication\n"); /* FIXME */
|
|
OUTF("FIXME: Possible IMSI in here\n");
|
|
OUTF("FIXME: Possible cipher mode here\n");
|
|
break;
|
|
case 2:
|
|
OUTF("--000010 Location Update Accept\n"); /* FIXME */
|
|
break;
|
|
case 4:
|
|
OUTF("--000100 Message Type: Locatoin Updating Reject\n");
|
|
break;
|
|
case 8:
|
|
OUTF("--001000 MM Location Update Request\n"); /* FIXME */
|
|
OUTF("FIXME: Possible IMSI in here\n");
|
|
OUTF("FIXME: Possible cipher mode here\n");
|
|
break;
|
|
case 0x12:
|
|
OUTF("--010010 Authentication Request\n");
|
|
data++;
|
|
AuthenticationRequest();
|
|
break;
|
|
case 0x14:
|
|
OUTF("--010100 Authentication Response\n");
|
|
data++;
|
|
AuthenticationResponse();
|
|
break;
|
|
case 0x19:
|
|
OUTF("--011001 MMidentityResponse\n");
|
|
OUTF("FIXME: Possible IMSI in here\n");
|
|
break;
|
|
case 0x1a:
|
|
OUTF("--011010 TMSI Realloc Command\n");
|
|
data++;
|
|
l2_TmsiReallocCommand();
|
|
break;
|
|
case 0x24: /* --100100 */
|
|
OUTF("--100100 MMcmServiceRequest\n");
|
|
data++;
|
|
l2_MMcmServiceRequest();
|
|
/* in multisupport2 and others! */
|
|
break;
|
|
default:
|
|
OUTF("UNKNWON\n");
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ProtDisc6 - Radio Resource Management Messages
|
|
*/
|
|
static void
|
|
l2_rrm()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
|
|
switch (data[0] & 0x3f)
|
|
{
|
|
case 0x00:
|
|
OUTF("00000000 System Information Type 13\n");
|
|
data++;
|
|
l2_RRsystemInfo13C();
|
|
break;
|
|
case 0x06:
|
|
OUTF("00000110 System Information Type 5ter\n");
|
|
data++;
|
|
l2_BcchAllocation();
|
|
break;
|
|
case 0x0d:
|
|
OUTF("00001101 Channel Release\n");
|
|
data++;
|
|
l2_ChannelRelease();
|
|
break;
|
|
case 0x15:
|
|
OUTF("00010101 RR Measurement Report C [FIXME]\n");
|
|
break;
|
|
case 0x16:
|
|
OUTF("00010110 RRclassmarkChange\n");
|
|
data++;
|
|
l2_RRclassmarkChange();
|
|
break;
|
|
case 0x19:
|
|
OUTF("00011001 RRsystemInfo1\n");
|
|
data++;
|
|
l2_RRsystemInfo1();
|
|
break;
|
|
case 0x1a:
|
|
OUTF("00011010 RRsystemInfo2\n");
|
|
data++;
|
|
l2_RRsystemInfo2();
|
|
break;
|
|
case 0x1B: /* 0001 1011 */
|
|
OUTF("00011011 RRsystemInfo3C\n");
|
|
data++;
|
|
l2_RRsystemInfo3C();
|
|
break;
|
|
case 0x1c:
|
|
OUTF("00011100 RRsystemInfo4-C\n");
|
|
data++;
|
|
l2_RRsystemInfo4C();
|
|
break;
|
|
case 0x1d:
|
|
/* From SDCCH */
|
|
OUTF("00011101 Neighbour Cells Description\n");
|
|
data++;
|
|
l2_NeighbourCellDescription();
|
|
break;
|
|
case 0x1e:
|
|
/* From SDCCH */
|
|
OUTF("00011110 System Information Type 6\n");
|
|
data++;
|
|
l2_RRsystemInfo6();
|
|
break;
|
|
case 0x21:
|
|
OUTF("00100001 Paging Request Type 1\n");
|
|
data++;
|
|
l2_RRpagingrequest1();
|
|
break;
|
|
case 0x22:
|
|
OUTF("00100010 Paging Request Type 2\n");
|
|
data++;
|
|
l2_RRpagingrequest2();
|
|
break;
|
|
case 0x24:
|
|
OUTF("00100100 Paging Request Type 3\n");
|
|
data++;
|
|
l2_RRpagingrequest3();
|
|
break;
|
|
case 0x27:
|
|
OUTF("0-100111 RRpagingResponse\n");
|
|
OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01);
|
|
data++;
|
|
l2_RRpagingresponse();
|
|
break;
|
|
case 0x29:
|
|
OUTF("0-101001 RR Assign Complete\n");
|
|
data++;
|
|
l2_RRassignComplete();
|
|
break;
|
|
case 0x2e:
|
|
OUTF("00101110 RR Assign Command\n");
|
|
data++;
|
|
l2_RRassignCommand();
|
|
break;
|
|
case 0x32:
|
|
OUTF("00110010 RR Cipher Mode Complete\n");
|
|
data++;
|
|
l2_RRciphModCompl();
|
|
break;
|
|
case 0x35:
|
|
OUTF("00110101 RR Cipher Mode Command\n");
|
|
data++;
|
|
l2_RRciphModCmd();
|
|
break;
|
|
case 0x3f:
|
|
OUTF("0-111111 RRimmediateAssignment\n");
|
|
OUTF("-x------ Send sequence number: %d\n", (data[0] >> 7) & 0x01);
|
|
data++;
|
|
l2_RRimmediateAssignment();
|
|
break;
|
|
default:
|
|
OUTF("???????? UNKNOWN. FIXME\n");
|
|
}
|
|
}
|
|
static void
|
|
l2_RRsystemInfo13C()
|
|
{
|
|
if (data >= end);
|
|
return;
|
|
if (data[0] >> 7)
|
|
OUTF("1------- SI 13 Restoctet present\n");
|
|
else
|
|
OUTF("0------- SI 13 Restoctet NOT present\n");
|
|
OUTF("%s BCCH_CHANGE_MARK : %d\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
|
|
switch (data[0] & 0x0f)
|
|
{
|
|
case 0x00:
|
|
OUTF("----0000 SI_CHANGE_FIELD : Update of unspecified SI messages\n");
|
|
break;
|
|
case 0x01:
|
|
OUTF("----00001 SI_CHANGE_FIELD : Update of unspecified SI1 messages\n");
|
|
break;
|
|
case 0x02:
|
|
OUTF("----0010 SI_CHANGE_FIELD : Update of unspecified SI2 messages\n");
|
|
break;
|
|
case 0x03:
|
|
OUTF("----0011 SI_CHANGE_FIELD : Update of unspecified SI3,4,7,8 messages\n");
|
|
break;
|
|
case 0x04:
|
|
OUTF("----0100 SI_CHANGE_FIELD : Update of unspecified SI9 messages\n");
|
|
break;
|
|
default:
|
|
OUTF("----???? Unknown %d\n", data[0] & 0x0f);
|
|
break;
|
|
}
|
|
OUTF("FIXME: implement me\n");
|
|
|
|
}
|
|
|
|
static void
|
|
l2_RRimmediateAssignment()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
|
|
/* Octect 4, 0x79 */
|
|
OUTF("%s\n", PageMode(data[0] & 0x03));
|
|
|
|
if ((data[0] >> 6) & 0x01)
|
|
OUTF("-1------ Two messages assign.: 1. message of..(continue)\n");
|
|
else
|
|
OUTF("-0------ No meaning\n");
|
|
if ((data[0] >> 5) & 0x01)
|
|
OUTF("--1----- Assigns a resource identified in the IA rest octets.\n");
|
|
else
|
|
OUTF("--0----- Downlink assig to MS: No meaning\n");
|
|
if ((data[0] >> 4) & 0x01)
|
|
{
|
|
OUTF("---1---- Temporary Block Flow (TBF)\n");
|
|
data++;
|
|
l2_RRimmediateAssTBFC();
|
|
return;
|
|
}
|
|
else
|
|
OUTF("---0---- This messages assigns a dedicated mode resource\n");
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
|
|
/* Channel Description */
|
|
ChannelDescriptionTwo();
|
|
|
|
if (data >= end)
|
|
return;
|
|
if (((data[0] >> 2) & 0x07) == 0)
|
|
l2_SingleChannel();
|
|
else if (((data[0] >> 4) & 0x01) == 1)
|
|
{
|
|
l2_HoppingChannel();
|
|
} else {
|
|
OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3);
|
|
}
|
|
}
|
|
|
|
static void
|
|
l2_SingleChannel()
|
|
{
|
|
int freq;
|
|
OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
|
|
OUTF("---000-- Single channel\n");
|
|
freq = (data[0] & 0x03) << 8;
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
freq |= data[0];
|
|
OUTF("........ Absolute RF channel number: %u\n", freq);
|
|
data++;
|
|
RequestReference();
|
|
TimingAdvance();
|
|
l2_MobileAllocation();
|
|
if (data >= end)
|
|
return;
|
|
}
|
|
|
|
static void
|
|
l2_HoppingChannel()
|
|
{
|
|
unsigned char maio = 0;
|
|
OUTF("%s Training seq. code : %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
|
|
OUTF("---1---- HoppingChannel\n");
|
|
maio = (data[0] & 0x0f) << 2;
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
maio |= (data[0] >> 6);
|
|
OUTF("........ MAIO %d\n", maio);
|
|
OUTF("%s Hopping Seq. Number: %d\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
|
|
|
|
data++;
|
|
RequestReference();
|
|
TimingAdvance();
|
|
l2_MobileAllocation();
|
|
if (data >= end)
|
|
return; /* finished. not truncated! */
|
|
|
|
OUTF("FIXME, more data left here???\n");
|
|
}
|
|
|
|
static void
|
|
l2_MobileAllocation()
|
|
{
|
|
int c = 64, pos;
|
|
char *str = "Mobile allocation RF chann.";
|
|
const unsigned char *thisend;
|
|
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Length of Mobile Allocation: %d\n", BitRowFill(data[0], 0xff), data[0]);
|
|
thisend = data + data[0] + 1;
|
|
if (thisend > end)
|
|
{
|
|
OUTF("xxxxxxxx ERROR: Packet to short or length to long\n");
|
|
thisend = end;
|
|
}
|
|
|
|
data++;
|
|
/* If mobile allocation has length 0 */
|
|
if (data >= thisend)
|
|
return;
|
|
|
|
while (data < thisend)
|
|
{
|
|
pos = 7;
|
|
while (pos >= 0)
|
|
{
|
|
if ((data[0] >> pos) & 1)
|
|
OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos));
|
|
pos--;
|
|
|
|
}
|
|
|
|
c -= 8;
|
|
data++;
|
|
if (c <= 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* From RRsystemInfo2
|
|
*/
|
|
static void
|
|
l2_BcchAllocation()
|
|
{
|
|
int c, pos;
|
|
char *str = "BCCH alloc. RF chan.: ";
|
|
|
|
#if 0
|
|
/* goeller script for Info2 outputs channels 128 + 127
|
|
* but opengpa outputs bitmap format for info2.
|
|
* We do what opengpa does. (correct?)
|
|
*/
|
|
if ((data[0] >> 7))
|
|
OUTF("1------- %s%d\n", str, 128);
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ %s%d\n", str, 127);
|
|
#endif
|
|
if ((data[0] >> 6) == 0x00)
|
|
OUTF("00------ Bitmap format: 0\n");
|
|
else {
|
|
OUTF("%s Bitmap format: UNKNOWN [FIXME]\n", BitRowFill(data[0], 0xc0));
|
|
RETTRUNK();
|
|
}
|
|
|
|
if ((data[0] & 0x8e) == 0x8e)
|
|
{
|
|
/* From System Information Type 5ter */
|
|
OUTF("1---111- Variable Bitmap SI5ter [FIXME]\n");
|
|
return;
|
|
}
|
|
|
|
if ((data[0] >> 5) & 1)
|
|
OUTF("--1----- Extension Indicator: The IE carries only a part of the BA\n");
|
|
else
|
|
OUTF("--0----- Extension Indicator: The IE carries the complete BA\n");
|
|
OUTF("---x---- BCCH alloc. seq. num: %d\n", (data[0] >> 4) & 1);
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- %s%d\n", str, 124);
|
|
if ((data[0] >> 2) & 1)
|
|
OUTF("-----1-- %s%d\n", str, 123);
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- %s%d\n", str, 122);
|
|
if (data[0] & 1)
|
|
OUTF("-------1 %s%d\n", str, 121);
|
|
|
|
data++;
|
|
c = 120;
|
|
while (data < end)
|
|
{
|
|
pos = 7;
|
|
while (pos >= 0)
|
|
{
|
|
if ((data[0] >> pos) & 1)
|
|
OUTF("%s %s%d\n", BitRow(data[0], pos), str, c - (7 - pos));
|
|
pos--;
|
|
|
|
}
|
|
|
|
c -= 8;
|
|
data++;
|
|
if (c <= 0)
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
l2_RRimmediateAssTBFC()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
|
|
/* GPRS Packet Channel Description */
|
|
OUTF("%s Channel Type : %d\n", BitRowFill(data[0], 0xf8), data[0] >> 3);
|
|
OUTF("%s Time Slot Number : %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
|
|
OUTF("%s Tranining Sequence Code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
|
|
if ((data[0] >> 4) & 0x01)
|
|
{
|
|
OUTF("---1---- Direct Encoding of Hopping Channels\n");
|
|
l2_RRimmAssTBFDirEncHoChaC();
|
|
return;
|
|
} else {
|
|
OUTF("---0---- non-hopping RF channel config or indirect encoding of hopping RFCC\n");
|
|
}
|
|
|
|
if ((data[0] >> 3) & 0x01)
|
|
{
|
|
OUTF("----1--- indirect encoding of hopping RF channel config\n");
|
|
} else {
|
|
OUTF("----0--- RRimmAssTBFaRFCN-C FIXME\n");
|
|
return;
|
|
}
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("xxxxxxxx MAIO [FIXME]\n");
|
|
|
|
data++;
|
|
RequestReference();
|
|
TimingAdvance();
|
|
l2_MobileAllocation();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("FIXME: implenet\n");
|
|
}
|
|
|
|
static void
|
|
l2_RRsystemInfo1()
|
|
{
|
|
int ca;
|
|
|
|
if (data + 1 >= end)
|
|
return;
|
|
switch (data[0] >> 6)
|
|
{
|
|
case 0x00:
|
|
OUTF("00------ Bitmap 0 format\n");
|
|
break;
|
|
case 0x01:
|
|
OUTF("10------ Bitmap format: (FIXME)\n");
|
|
break;
|
|
default:
|
|
OUTF("%s Bitmap %d format (FIXME)\n", BitRowFill(data[0], 0xc0), data[0] >> 6);
|
|
}
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- Cell Allocation : ARFCN 124\n");
|
|
if ((data[0] >> 2) & 1)
|
|
OUTF("-----1-- Cell Allocation : ARFCN 123\n");
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- Cell Allocation : ARFCN 122\n");
|
|
if (data[0] & 1)
|
|
OUTF("-------1 Cell Allocation : ARFCN 121\n");
|
|
|
|
ca = 120;
|
|
while (ca > 0)
|
|
{
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
if ((data[0] >> 7) & 1)
|
|
OUTF("1------- Cell Allocation : ARFCN %d\n", ca);
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ Cell Allocation : ARFCN %d\n", ca - 1);
|
|
if ((data[0] >> 5) & 1)
|
|
OUTF("--1----- Cell Allocation : ARFCN %d\n", ca - 2);
|
|
if ((data[0] >> 4) & 1)
|
|
OUTF("---1---- Cell Allocation : ARFCN %d\n", ca - 3);
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- Cell Allocation : ARFCN %d\n", ca - 4);
|
|
if ((data[0] >> 2) & 1)
|
|
OUTF("-----1-- Cell Allocation : ARFCN %d\n", ca - 5);
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- Cell Allocation : ARFCN %d\n", ca - 6);
|
|
if (data[0] & 1)
|
|
OUTF("-------1 Cell Allocation : ARFCN %d\n", ca - 7);
|
|
|
|
ca -= 8;
|
|
}
|
|
|
|
data++;
|
|
|
|
l2_RachControlParameters();
|
|
OUTF("FIXME: NCH Position\n");
|
|
if (data >= end)
|
|
return;
|
|
}
|
|
|
|
static void
|
|
l2_RachControlParameters()
|
|
{
|
|
int ca = -1;
|
|
|
|
if (data >= end)
|
|
return;
|
|
|
|
if (((data[0] >> 6) & 0x03) == 0)
|
|
ca = 1;
|
|
else if (((data[0] >> 6) & 0x03) == 0x01)
|
|
ca = 2;
|
|
else if (((data[0] >> 6) & 0x03) == 0x02)
|
|
ca = 4;
|
|
else if (((data[0] >> 6) & 0x03) == 0x03)
|
|
ca = 7;
|
|
OUTF("%s Max. of retransmiss : %u\n", BitRowFill(data[0], 0xc0), ca);
|
|
if (((data[0] >> 2) & 0x0f) <= 9)
|
|
{
|
|
ca = ((data[0] >> 2) & 0x0f) + 3;
|
|
} else {
|
|
switch ((data[0] >> 2) & 0x0f)
|
|
{
|
|
case 10: /* --1010-- */
|
|
ca = 14;
|
|
break;
|
|
case 11:
|
|
ca = 16;
|
|
break;
|
|
case 12:
|
|
ca = 20;
|
|
break;
|
|
case 13:
|
|
ca = 25;
|
|
break;
|
|
case 14:
|
|
ca = 32;
|
|
break;
|
|
case 15:
|
|
ca = 50;
|
|
break;
|
|
default:
|
|
ca = -1;
|
|
break;
|
|
}
|
|
}
|
|
OUTF("%s slots to spread TX : %u\n", BitRowFill(data[0], 0x3c), ca);
|
|
switch ((data[0] >> 1) & 0x01)
|
|
{
|
|
case 0:
|
|
OUTF("------0- The cell is barred : no\n");
|
|
break;
|
|
case 1:
|
|
OUTF("------1- The cell is barred : yes\n");
|
|
break;
|
|
}
|
|
|
|
switch (data[0] & 0x01)
|
|
{
|
|
case 0:
|
|
OUTF("-------0 Call reestabl.i.cell: allowed\n");
|
|
break;
|
|
case 1:
|
|
OUTF("-------1 Cell reestabl.i.cell: not allowed\n");
|
|
}
|
|
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
switch ((data[0] >> 2) & 0x01)
|
|
{
|
|
case 0:
|
|
OUTF("-----0-- Emergency call EC 10: allowed\n");
|
|
break;
|
|
case 1:
|
|
OUTF("-----1-- Emergency call EC 10: not allowed\n");
|
|
break;
|
|
}
|
|
OUTF("%s Acc ctrl cl 11-15: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xf8));
|
|
OUTF("%s Acc ctrl cl 8- 9: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0x03));
|
|
OUTF("%s Ordinary subscribers (8)\n", BitRowFill(data[0], 0x01));
|
|
OUTF("%s Ordinary subscribers (9)\n", BitRowFill(data[0], 0x02));
|
|
OUTF("%s Emergency call (10): %s\n", BitRowFill(data[0], 0x04), ((data[0] >> 4) & 1)?"Class 11-15 only":"Everyone");
|
|
OUTF("%s Operator Specific (11)\n", BitRowFill(data[0], 0x08));
|
|
OUTF("%s Security service (12)\n", BitRowFill(data[0], 0x10));
|
|
OUTF("%s Public service (13)\n", BitRowFill(data[0], 0x20));
|
|
OUTF("%s Emergency service (14)\n", BitRowFill(data[0], 0x40));
|
|
OUTF("%s Network Operator (15)\n", BitRowFill(data[0], 0x80));
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Acc ctrl cl 0- 7: 0 = permitted, 1 = forbidden\n", BitRowFill(data[0], 0xff));
|
|
OUTF("%s Ordinary subscribers (0-7)\n", BitRowFill(data[0], 0xff));
|
|
data++;
|
|
}
|
|
|
|
static char *
|
|
BitRow(unsigned char c, int pos)
|
|
{
|
|
unsigned char bit = 0;
|
|
static char buf[9];
|
|
|
|
if ((c >> pos) & 1)
|
|
bit = 1;
|
|
|
|
if (pos == 0)
|
|
snprintf(buf, sizeof buf, "-------%d", bit);
|
|
else if (pos == 1)
|
|
snprintf(buf, sizeof buf, "------%d-", bit);
|
|
else if (pos == 2)
|
|
snprintf(buf, sizeof buf, "-----%d--", bit);
|
|
else if (pos == 3)
|
|
snprintf(buf, sizeof buf, "----%d---", bit);
|
|
else if (pos == 4)
|
|
snprintf(buf, sizeof buf, "---%d----", bit);
|
|
else if (pos == 5)
|
|
snprintf(buf, sizeof buf, "--%d-----", bit);
|
|
else if (pos == 6)
|
|
snprintf(buf, sizeof buf, "-%d------", bit);
|
|
else if (pos == 7)
|
|
snprintf(buf, sizeof buf, "%d-------", bit);
|
|
|
|
return buf;
|
|
}
|
|
|
|
static char *
|
|
BitRowFill(unsigned char c, unsigned char mask)
|
|
{
|
|
static char buf[9];
|
|
|
|
memset(buf, '-', sizeof buf);
|
|
buf[sizeof buf - 1] = '\0';
|
|
int i = 0;
|
|
while (i < 8)
|
|
{
|
|
if ((mask >> i) & 1)
|
|
{
|
|
if ((c >> i) & 1)
|
|
buf[7 - i] = '1';
|
|
else
|
|
buf[7 - i] = '0';
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
static void
|
|
l2_RRsystemInfo2()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
l2_BcchAllocation();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
int c = 7;
|
|
while (c >= 0)
|
|
{
|
|
if ((data[0] >> c) & 1)
|
|
OUTF("%s BCCH carrier with NCC = %d is permitted for monitoring\n", BitRow(data[0], c), c);
|
|
c--;
|
|
}
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
l2_RachControlParameters();
|
|
|
|
if (data > end) /* Note: not >= */
|
|
RETTRUNK();
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
l2_RRsystemInfo2ter()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
if ((data[0] >> 7) == 0)
|
|
OUTF("%s Bitmap 0 format\n", BitRowFill(data[0], 0x8e));
|
|
else {
|
|
/* 0x8e = 10001110 */
|
|
if (((data[0] >> 1) & 0x07) == 0x04)
|
|
OUTF("1---100- 1024 range\nFIXME\n");
|
|
else if (((data[0] >> 1) & 0x07) == 0x05)
|
|
OUTF("1---101- 512 range\nFIXME\n");
|
|
else if (((data[0] >> 1) & 0x07) == 0x06)
|
|
OUTF("1---110- 128 range\nFIXME\n");
|
|
else if (((data[0] >> 1) & 0x07) == 0x07)
|
|
OUTF("1---111- variable Bitmap\nFIXME\n");
|
|
else
|
|
OUTF("1---xxx- UNKNOWN 0x%08x\n", data[0]);
|
|
}
|
|
OUTF("FIXME\n");
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* RRsystemInfo4-C
|
|
*/
|
|
static void
|
|
l2_RRsystemInfo4C()
|
|
{
|
|
if (data + 2 >= end)
|
|
RETTRUNK();
|
|
l2_MccMncLac();
|
|
CellSelectionParameters();
|
|
l2_RachControlParameters();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("FIXME\n");
|
|
}
|
|
|
|
/*
|
|
* Output MCC, MNC and LAC. consume 5 bytes.
|
|
*/
|
|
static void
|
|
l2_MccMncLac()
|
|
{
|
|
if (data + 2 >= end)
|
|
return;
|
|
unsigned short lac;
|
|
|
|
l2_MNCC("Mobile Country Code", data[0] & 0x0f, (data[0] >> 4) & 0x0f, data[1] & 0x0f);
|
|
data++;
|
|
l2_MNCC("Mobile Network Code", data[1] & 0x0f, (data[1] >> 4) & 0x0f, (data[0] >> 4) & 0x0f);
|
|
data += 2;
|
|
|
|
if (data + 1 >= end)
|
|
return;
|
|
|
|
lac = data[0];
|
|
lac = (lac << 8) | data[1];
|
|
OUTF("%-8u [0x%02x%02x] Local Area Code\n", lac, data[0], data[1]);
|
|
data += 2;
|
|
}
|
|
/*
|
|
* RRsystemINfo3-C
|
|
*/
|
|
static void
|
|
l2_RRsystemInfo3C()
|
|
{
|
|
CellIdentity();
|
|
l2_MccMncLac();
|
|
|
|
ControlChannelDescription();
|
|
CellOptionsBcch();
|
|
CellSelectionParameters();
|
|
l2_RachControlParameters();
|
|
|
|
/* FIXME: complete here */
|
|
}
|
|
|
|
static void
|
|
l2_RRsystemInfo6()
|
|
{
|
|
CellIdentity();
|
|
l2_MccMncLac();
|
|
CellOptionsBcch();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Network Colour Code: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
}
|
|
|
|
static void
|
|
CellIdentity()
|
|
{
|
|
unsigned short id;
|
|
|
|
if (data + 1 >= end)
|
|
return;
|
|
|
|
id = data[0];
|
|
id = (id << 8) | data[1];
|
|
OUTF("%-8u [0x%02x%02x] Cell identity\n", id, data[0], data[1]);
|
|
data += 2;
|
|
}
|
|
|
|
static void
|
|
ControlChannelDescription()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Spare bit (should be 0)\n", BitRow(data[0], 7));
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ MSs in the cell shall apply IMSI attach/detach procedure\n");
|
|
else
|
|
OUTF("-0------ MSs in cell are not allowed attach/detach procedure\n");
|
|
OUTF("%s Number of blocks: %u\n", BitRowFill(data[0], 0x38), (data[0] >> 3) & 0x07);
|
|
|
|
switch (data[0] & 0x07)
|
|
{
|
|
case 0x00:
|
|
OUTF("-----000 1 basic physical channel for CCCH, not combined with SDCCHs\n");
|
|
break;
|
|
case 0x01:
|
|
OUTF("-----001 1 basic physical channel for CCCH, combined with SDCCHs\n");
|
|
break;
|
|
case 0x02:
|
|
OUTF("-----010 2 basic physical channel for CCCH, not combined with SDCCHs\n");
|
|
break;
|
|
case 0x04:
|
|
OUTF("-----100 3 basic physical channel for CCCH, not combined with SDCCHs\n");
|
|
break;
|
|
case 0x06:
|
|
OUTF("-----110 4 basic physical channel for CCCH, not combined with SDCCHs\n");
|
|
break;
|
|
default:
|
|
OUTF("%s Unknown CCCH config (ERROR)\n", BitRowFill(data[0], 0x07));
|
|
break;
|
|
}
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s spare bits (should be 0)\n", BitRowFill(data[0], 0xf8));
|
|
OUTF("%s %u multi frames period for paging request\n", BitRowFill(data[0], 0x07), (data[0] & 0x07) + 2);
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s T3212 TimeOut value: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
CellOptionsBcch()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s spare bit (should be 0)\n", BitRowFill(data[0], 0x80));
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ Power control indicator is set\n");
|
|
else
|
|
OUTF("-0------ Power control indicator is not set\n");
|
|
|
|
if (((data[0] >> 4) & 0x03) == 0x00)
|
|
OUTF("--00---- MSs may use uplink DTX\n");
|
|
else if (((data[0] >> 4) & 0x03) == 0x01)
|
|
OUTF("--01---- MSs shall use uplink DTX\n");
|
|
else if (((data[0] >> 4) & 0x03) == 0x02)
|
|
OUTF("--10---- MSs shall not use uplink DTX\n");
|
|
else
|
|
OUTF("%s DTX UNKNOWN [ERROR]\n", BitRowFill(data[0], 0x30));
|
|
|
|
OUTF("%s Radio Link Timeout: %u\n", BitRowFill(data[0], 0x0f), ((data[0] & 0x0f) + 1 ) * 4);
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_MNCC(const char *str, unsigned char a, unsigned char b, unsigned char c)
|
|
{
|
|
char buf[128];
|
|
char f[12];
|
|
|
|
snprintf(f, sizeof f, "%x%x%x", a, b, c);
|
|
/* Nokia netmonitor shows NC's like '30F' and '10F' */
|
|
snprintf(buf, sizeof buf, "%-8s %s\n", f, str);
|
|
|
|
#if 0
|
|
buf[0] = '\0';
|
|
if (a != 0x0f)
|
|
{
|
|
snprintf(buf, sizeof buf, "%x", a);
|
|
if (b != 0x0f)
|
|
{
|
|
snprintf(buf + 1, sizeof buf - 1, "%x", b);
|
|
if (c != 0x0f)
|
|
snprintf(buf + 2, sizeof buf - 2, "%x", c);
|
|
}
|
|
}
|
|
snprintf(buf + strlen(buf), sizeof buf - strlen(buf), " - %s\n", str);
|
|
#endif
|
|
|
|
OUTF(buf);
|
|
}
|
|
|
|
static char *
|
|
PageMode(unsigned char mode)
|
|
{
|
|
switch (mode)
|
|
{
|
|
case 0:
|
|
return "------00 Page Mode: Normal paging";
|
|
case 1:
|
|
return "------01 Page Mode: Extended paging";
|
|
case 2:
|
|
return "------10 Page Mode: Paging reorganisation";
|
|
case 3:
|
|
return "------11 Page Mode: reserved / same as before";
|
|
}
|
|
|
|
return "------?? UNKNOWN\n";
|
|
}
|
|
|
|
static void
|
|
l2_RRpagingrequest1()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
|
|
OUTF("%s\n", PageMode(data[0] & 0x3));
|
|
|
|
/* FIXME complete here */
|
|
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
|
|
l2_MobId();
|
|
if (data >= end)
|
|
return; /* sometimes it's end here */
|
|
if (data[0] == 0x17)
|
|
{
|
|
data++;
|
|
l2_MobId();
|
|
return;
|
|
}
|
|
OUTF("ERR: wrong data\n");
|
|
}
|
|
|
|
static void
|
|
l2_ChannelNeeded(char *str, unsigned char ch)
|
|
{
|
|
switch (ch)
|
|
{
|
|
case 0x00:
|
|
OUTF("%s Channel Needed: Any channel\n", str);
|
|
break;
|
|
case 0x01:
|
|
OUTF("%s Channel Needed: SDCCH\n", str);
|
|
break;
|
|
case 0x02:
|
|
OUTF("%s Channel Needed: TCH/F (Full rate)\n", str);
|
|
break;
|
|
case 0x03:
|
|
OUTF("%s Channel Needed: TCH/H or TCH/F (Dual rate)\n", str);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
l2_RRpagingrequest2()
|
|
{
|
|
if (data >= end)
|
|
return;
|
|
OUTF("%s\n", PageMode(data[0] & 0x03));
|
|
|
|
l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03);
|
|
l2_ChannelNeeded("xx------ (second)", data[0] >> 6);
|
|
|
|
data++;
|
|
if (data + 3 >= end)
|
|
RETTRUNK();
|
|
OUTF("........ Mob. Ident 1 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]);
|
|
data += 4;
|
|
if (data + 3 >= end)
|
|
RETTRUNK();
|
|
OUTF("........ Mob. Ident 2 (P)TMSI: %02X%02X%02X%02X\n", data[0], data[1], data[2], data[3]);
|
|
data += 4;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (data[0] == 0x17)
|
|
{
|
|
data++;
|
|
l2_MobId();
|
|
return;
|
|
}
|
|
|
|
OUTF("FIXME, unknown\n");
|
|
}
|
|
|
|
static void
|
|
l2_RRpagingrequest3()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s\n", PageMode(data[0] & 0x03));
|
|
l2_ChannelNeeded("--xx---- (first)", (data[0] >> 4) & 0x03);
|
|
l2_ChannelNeeded("xx------ (second)", data[0] >> 6);
|
|
data++;
|
|
|
|
int c = 0;
|
|
while (c++ < 4)
|
|
{
|
|
if (data + 3 >= end)
|
|
RETTRUNK();
|
|
OUTF("........ Mob. Ident %u (P)TMSI: %02X%02X%02X%02X\n", c, data[0], data[1], data[2], data[3]);
|
|
data += 4;
|
|
}
|
|
}
|
|
|
|
static void
|
|
l2_MobId()
|
|
{
|
|
const unsigned char *thisend = end;
|
|
unsigned char len = data[0];
|
|
char odd = 0;
|
|
int bcd = 0;
|
|
|
|
data++;
|
|
if (data >= end)
|
|
return;
|
|
|
|
if ((data[0] >> 3) & 1)
|
|
odd = 1;
|
|
|
|
switch (data[0] & 0x07)
|
|
{
|
|
case 0:
|
|
OUTF("-----000 Type of identity: No Identity\n");
|
|
break;
|
|
case 1:
|
|
OUTF("-----001 Type of identity: IMSI\n");
|
|
bcd = 1;
|
|
break;
|
|
case 2:
|
|
OUTF("-----010 Type of identity: IMEI\n");
|
|
bcd = 1;
|
|
break;
|
|
case 3:
|
|
OUTF("-----011 Type of identity: IMEISV\n");
|
|
bcd = 1;
|
|
break;
|
|
case 4:
|
|
OUTF("-----100 Type of identity: TMSI/P-TMSI\n");
|
|
break;
|
|
default:
|
|
OUTF("-----000 Type of identity: UNKNOWN\n");
|
|
return;
|
|
}
|
|
if (len <= 0)
|
|
return;
|
|
|
|
/* Nokia Netmonitor never outputs the first value */
|
|
//OUTF("%x", data[0] >> 4);
|
|
unsigned char c;
|
|
c = data[0] >> 4;
|
|
len--;
|
|
data++;
|
|
if (len <= 0)
|
|
return;
|
|
|
|
OUTF("-------- ID(%d/%s): ", len, odd?"odd":"even");
|
|
|
|
if (data + len < thisend)
|
|
thisend = data + len;
|
|
if (bcd)
|
|
{
|
|
OUT("%X", c);
|
|
while (data < thisend)
|
|
{
|
|
if ((data + 1 == thisend) && (!odd))
|
|
OUT("%X", data[0] & 0x0f);
|
|
else
|
|
OUT("%X%X", data[0] & 0x0f, (data[0] >> 4) & 0x0f);
|
|
data++;
|
|
}
|
|
} else {
|
|
while (data < thisend)
|
|
{
|
|
if ((data + 1 == thisend) && (odd))
|
|
OUT("%X", (data[0] >> 4 ) & 0x0f);
|
|
else
|
|
OUT("%X%X", (data[0] >> 4) & 0x0f, data[0] & 0x0f);
|
|
data++;
|
|
}
|
|
}
|
|
OUT("\n");
|
|
}
|
|
|
|
|
|
static void CellSelectionParameters()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
switch (data[0] >> 5)
|
|
{
|
|
case 0:
|
|
OUTF("000----- Cell Reselect Hyst. : 0 db RXLEV\n");
|
|
break;
|
|
case 1:
|
|
OUTF("001----- Cell Reselect Hyst. : 2 db RXLEV\n");
|
|
break;
|
|
case 2:
|
|
OUTF("010----- Cell Reselect Hyst. : 4 db RXLEV\n");
|
|
break;
|
|
case 3:
|
|
OUTF("011----- Cell Reselect Hyst. : 6 db RXLEV\n");
|
|
break;
|
|
case 4:
|
|
OUTF("100----- Cell Reselect Hyst. : 8 db RXLEV\n");
|
|
break;
|
|
case 5:
|
|
OUTF("101----- Cell Reselect Hyst. : 10 db RXLEV\n");
|
|
break;
|
|
case 6:
|
|
OUTF("110----- Cell Reselect Hyst. : 12 db RXLEV\n");
|
|
break;
|
|
case 7:
|
|
OUTF("111----- Cell Reselect Hyst. : 14 db RXLEV\n");
|
|
break;
|
|
}
|
|
OUTF("---xxxxx Max Tx power level: %d\n", data[0] & 0x1f);
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (data[0] >> 7)
|
|
OUTF("1------- Additional cells in SysInfo 16,17\n");
|
|
else
|
|
OUTF("0------- No additional cells in SysInfo 7-8\n");
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ New establishm cause: supported\n");
|
|
else
|
|
OUTF("-0------ New establishm cause: not supported\n");
|
|
OUTF("--xxxxxx RXLEV Access Min permitted = -110 + %ddB\n", data[0] & 0x3f);
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_RRimmAssTBFDirEncHoChaC()
|
|
{
|
|
unsigned char maio = (data[0] & 0x0f) << 4;
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
maio |= (data[0] >> 6);
|
|
OUTF("xxxxxxxx MAIO: %u\n", maio);
|
|
OUTF("%s HSN: %u\n", BitRowFill(data[0], 0x3f), data[0] & 0x3f);
|
|
data++;
|
|
|
|
RequestReference();
|
|
|
|
TimingAdvance();
|
|
l2_MobileAllocation();
|
|
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] == 0x7c)
|
|
{
|
|
StartingTime();
|
|
return;
|
|
}
|
|
OUTF("FIXME: implement me\n");
|
|
}
|
|
|
|
static void
|
|
RequestReference()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
/* Request Reference */
|
|
if ((data[0] >> 5) == 0)
|
|
OUTF("000----- Establishing Cause : All other cases\n");
|
|
else if ((data[0] >> 5) == 0x01)
|
|
OUTF("001----- Establishing Cause : All other cases\n");
|
|
else if ((data[0] >> 5) == 0x02)
|
|
OUTF("010----- Establishing Cause : All other cases\n");
|
|
else if ((data[0] >> 5) == 0x03)
|
|
OUTF("011----- Establishing Cause : All other cases\n");
|
|
else if ((data[0] >> 5) == 0x04)
|
|
OUTF("100----- Establishing Cause: Answer to paging\n");
|
|
else if ((data[0] >> 5) == 0x05)
|
|
OUTF("101----- Establishing Cause: Emergency call\n");
|
|
else if ((data[0] >> 5) == 0x07)
|
|
OUTF("111----- Establishing Cause: Other services req. by user\n");
|
|
/* Random refernce must be 5 bit long ?! */
|
|
// else if ((data[0] >> 4) == 0x05)
|
|
// OUTF("0101---- Establishing Cause: Originating data call from dual rate mobile station\n");
|
|
// else if ((data[0] >> 4) == 0x02)
|
|
// OUTF("0010---- Establishing Cause: Answer to paging\n");
|
|
else
|
|
OUTF("%s Establishing Cause: UNKNOWN [FIXME}\n", BitRowFill(data[0], 0xe0));
|
|
|
|
OUTF("---xxxxx Random Reference : %d\n", data[0] & 0x1f);
|
|
|
|
data++;
|
|
if (data + 1>= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("xxxxxxxx T1/T2/T3\n");
|
|
data++;
|
|
OUTF("xxxxxxxx T1/T2/T3\n");
|
|
data++;
|
|
/* END Request Reference */
|
|
}
|
|
|
|
static void
|
|
TimingAdvance()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("--xxxxxx Timing advance value: %d\n", data[0] & 0x3f);
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
StartingTime()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("01111100 Starting Time block\n");
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
unsigned char t3;
|
|
OUTF("%s T1 Frame Number: %u\n", BitRowFill(data[0], 0xf8), data[0] >> 3);
|
|
t3 = (data[0] & 0x07) << 5;
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
t3 |= (data[0] >> 5);
|
|
OUTF("%s T2 Frame Number: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f);
|
|
OUTF("........ T3 Frame Number: %u\n", t3);
|
|
}
|
|
|
|
/*
|
|
* RRsystemInfo5
|
|
*/
|
|
static void
|
|
l2_NeighbourCellDescription()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
l2_BcchAllocation();
|
|
}
|
|
|
|
|
|
static void
|
|
l2_ChannelRelease()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s\n", id_list_get(list_ChannelRelease, data[0]));
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_MMcmServiceRequest()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
|
|
OUTF("%s\n", id_list_get(list_RequestServiceType, data[0] & 0x0f));
|
|
data++;
|
|
MSClassMarkTwo();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (data[0] == 0x20)
|
|
{
|
|
OUTF("FIXME: classmark3\n");
|
|
return;
|
|
}
|
|
|
|
l2_MobId();
|
|
}
|
|
|
|
static void
|
|
MSClassMarkTwo()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s MS Classmark 2 length: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (((data[0] >> 5) & 0x03) == 0)
|
|
OUTF("-00----- Revision Level: Phase 1\n");
|
|
else if (((data[0] >> 5) & 0x03) == 1)
|
|
OUTF("-01----- Revision Level: Phase 2\n");
|
|
else
|
|
OUTF("-xx----- Revision Level: Unknown\n");
|
|
if (((data[0] >> 4) & 1) == 0)
|
|
OUTF("---0---- Controlled early classmark sending: Not implemented\n");
|
|
else
|
|
OUTF("---1---- Controlled early classmark sending: Implemented\n");
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- A5/1 not available\n");
|
|
else
|
|
OUTF("----0--- A5/1 available\n");
|
|
|
|
OUTF("%s RF power class capability: Class %u\n", BitRowFill(data[0], 0x07), (data[0] & 0x07) + 1);
|
|
|
|
data++;
|
|
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ Pseudo Sync Capability: present\n");
|
|
else
|
|
OUTF("-1------ Pseudo Sync Capability: not present\n");
|
|
|
|
if (((data[0] >> 4) & 0x03) == 0)
|
|
OUTF("--00---- SS Screening: Phase 1 default value\n");
|
|
else if (((data[0] >> 4) & 0x03) == 1)
|
|
OUTF("--01---- SS Screening: Phase 2 error handling\n");
|
|
else
|
|
OUTF("--xx---- SS Screening: UNKNOWN\n");
|
|
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- Mobile Terminated Point to Point SMS: supported\n");
|
|
else
|
|
OUTF("----0--- Mobile Terminated Point to Point SMS: not supported\n");
|
|
|
|
if ((data[0] >> 2) & 1)
|
|
OUTF("-----1-- VoiceBroadcastService: supported\n");
|
|
else
|
|
OUTF("-----0-- VoiceBroadcastService: not supported\n");
|
|
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- VoiceGroupCallService: supported\n");
|
|
else
|
|
OUTF("------0- VoiceGroupCallService: not supported\n");
|
|
|
|
if (data[0] & 1)
|
|
OUTF("-------1 MS supports E-GSM or R-GSM: supported\n");
|
|
else
|
|
OUTF("-------0 MS supports E-GSM or R-GSM: not supported\n");
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
|
|
if ((data[0] >> 7) & 1)
|
|
OUTF("1------- CM3 option: supported\n");
|
|
else
|
|
OUTF("0------- CM3 option: not supported\n");
|
|
|
|
if ((data[0] >> 5) & 1)
|
|
OUTF("--1----- LocationServiceValueAdded Capability: supported\n");
|
|
else
|
|
OUTF("--0----- LocationServiceValueAdded Capability: not supported\n");
|
|
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- SoLSA Capability: supported\n");
|
|
else
|
|
OUTF("----0--- SoLSA Capability: not supported\n");
|
|
|
|
if ((data[0] >> 1) & 1)
|
|
OUTF("------1- A5/3 available\n");
|
|
else
|
|
OUTF("------0- A5/3 not available\n");
|
|
|
|
if (data[0] & 1)
|
|
OUTF("-------1 A5/2: available\n");
|
|
else
|
|
OUTF("-------0 A5/2: not available\n");
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_RRciphModCmd()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (((data[0] >> 1) & 0x07) == 0x07)
|
|
OUTF("----111- Cipher: reserved [UNKNOWN]\n");
|
|
else
|
|
OUTF("%s Cipher: A5/%u\n", BitRowFill(data[0], 0x0e), ((data[0] >> 1) & 0x07) + 1);
|
|
|
|
|
|
if (data[0] & 1)
|
|
OUTF("-------1 Start ciphering\n");
|
|
else
|
|
OUTF("-------0 No ciphering\n");
|
|
|
|
if ((data[0] >> 4) & 1)
|
|
OUTF("---1---- Cipher Response: IMEISV shall be included\n");
|
|
else
|
|
OUTF("---0---- Cipher Response: IMEISV shall not be included\n");
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_RRciphModCompl()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (data[0] != 0x17)
|
|
return;
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
l2_MobId();
|
|
}
|
|
|
|
static void
|
|
l2_TmsiReallocCommand()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
l2_MccMncLac();
|
|
l2_MobId();
|
|
}
|
|
|
|
static void
|
|
l2_sms()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if ((data[0] == 0x04))
|
|
OUTF("00000100 Type: CP-ACK\n");
|
|
else if (data[0] == 0x10)
|
|
OUTF("00010000 Type: CP-ERROR\n");
|
|
else if (data[0] == 1) {
|
|
OUTF("00000001 Type: CP-DATA\n");
|
|
data++;
|
|
cpData();
|
|
} else
|
|
OUTF("%s UNKNOWN\n", BitRowFill(data[0], 0xff));
|
|
}
|
|
|
|
static void
|
|
cpDataUp()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Parameter %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
data++;
|
|
Address("SMSC");
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
/* FIXME: Be more detailed here about message flags */
|
|
OUTF("%s Message Flags: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data + 1 >= end)
|
|
RETTRUNK();
|
|
int num = data[0] << 8;
|
|
OUTF("%s Reference Number [continue]\n", BitRowFill(data[0], 0xff));
|
|
data++;
|
|
num |= data[0];
|
|
OUTF("%s Reference Number: %u\n", BitRowFill(data[0], 0xff), num);
|
|
data++;
|
|
|
|
/* Destination address */
|
|
Address("Destination");
|
|
SmsProtocolDataValidity();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
}
|
|
|
|
static void
|
|
cpData()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if ((data[0] & 1) == 0)
|
|
{
|
|
//OUTF("xxxxxxx0 cpDataUp FIXME\n");
|
|
//data++;
|
|
cpDataUp();
|
|
return;
|
|
}
|
|
OUTF("%s Parameter\n", BitRowFill(data[0], 0xff));
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Parameter\n", BitRowFill(data[0], 0xff));
|
|
if (++data >= end)
|
|
return; /* Can happen that msg terminated here... */
|
|
|
|
Address("SMSC");
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s TP-MTI, TP-MMS, TP-SRI, TP-UDIH, TP-RP: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Reference number: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if ((data[0]) == 0x44)
|
|
{
|
|
OUTF("FIXME: ems_type\n");
|
|
return;
|
|
}
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Parameter\n", BitRowFill(data[0], 0xff));
|
|
data++;
|
|
|
|
Address("Destination");
|
|
SmsProtocolDataValidity();
|
|
|
|
int c = 0;
|
|
while (c++ < 7)
|
|
{
|
|
OUTF("%s Parameter%u\n", BitRowFill(data[0], 0xff), c);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
}
|
|
OUTF("FIXME %p < %p\n", data, end);
|
|
}
|
|
|
|
static void
|
|
Address(const char *str)
|
|
{
|
|
int len;
|
|
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
len = data[0];
|
|
OUTF("%s %s Address Length: %u\n", BitRowFill(data[0], 0xff), str, data[0]);
|
|
data++;
|
|
if (len <= 0)
|
|
return;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] >> 7)
|
|
OUTF("1------- Extension\n");
|
|
|
|
OUTF("%s\n", id_list_get(list_SMSCAddressType, (data[0] >> 4) & 0x07));
|
|
OUTF("%s\n", id_list_get(list_SMSCAddressNumberingPlan, data[0] & 0x0f));
|
|
len--;
|
|
data++;
|
|
if (len <= 0)
|
|
return;
|
|
const unsigned char *thisend = data + len;
|
|
if (thisend > end)
|
|
thisend = end;
|
|
|
|
OUTF("-------- Number(%d): ", len);
|
|
while (data < thisend)
|
|
{
|
|
if ((data[0] >> 4) == 0x0f)
|
|
OUT("%X", data[0] & 0x0f);
|
|
else
|
|
OUT("%X%X", data[0] & 0x0f, data[0] >> 4);
|
|
data++;
|
|
}
|
|
OUT("\n");
|
|
}
|
|
|
|
|
|
static void
|
|
l2_RRpagingresponse()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if ((data[0] & 0x07) == 0x07)
|
|
OUTF("-----111 Cipher key sequence: Key not available!\n");
|
|
else
|
|
OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
|
|
|
|
OUTF("%s Ciphering key sequence: %u\n", BitRowFill(data[0], 0x70), (data[0] >> 4) & 0x07);
|
|
|
|
data++;
|
|
MSClassMarkTwo();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
l2_MobId();
|
|
}
|
|
|
|
static void
|
|
l2_RRassignCommand()
|
|
{
|
|
ChannelDescriptionTwo();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Training seq. code: %d\n", BitRowFill(data[0], 0xe0), data[0] >> 5);
|
|
if (((data[0] >> 2) & 0x07) == 0x00)
|
|
l2_SingleChannelAssCom();
|
|
else if (((data[0] >> 4) & 1) == 0x01)
|
|
l2_HoppingChannelAssCom();
|
|
else
|
|
OUTF("xxx0??xxx UNKNOWN %d\n", (data[0] >> 3) & 0x3);
|
|
}
|
|
|
|
static void
|
|
l2_RRassignComplete()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s\n", id_list_get(list_ChannelRelease, data[0]));
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
ChannelDescriptionTwo()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Timeslot number: %d\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
|
|
OUTF("%s Channel Description: %s\n", BitRowFill(data[0], 0xf8), id_list_get(list_ChannelDescriptionTwo, data[0] >> 3));
|
|
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_SingleChannelAssCom()
|
|
{
|
|
int freq = (data[0] & 0x03) << 8;
|
|
|
|
data++;
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
freq |= data[0];
|
|
OUTF("........ Absolute RF channel number: %u\n", freq);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Power Level: %u\n", BitRowFill(data[0], 0x1f), data[0] & 0x1f);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
if (data[0] != 0x63)
|
|
return;
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s\n", id_list_get(list_ChannelMode, data[0]));
|
|
}
|
|
|
|
static void
|
|
l2_HoppingChannelAssCom()
|
|
{
|
|
OUTF("FIXME %s\n", __func__);
|
|
}
|
|
|
|
static void
|
|
CCalerting()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] != 0x1e)
|
|
return;
|
|
|
|
data++;
|
|
ProgressIndicator();
|
|
}
|
|
|
|
static void
|
|
ProgressIndicator()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Length of IE Progress Indicator: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_CodingStandard, (data[0] >> 5) & 0x03));
|
|
OUTF("%s Location: %s\n", BitRowFill(data[0], 0x0f), id_list_get(list_Location, data[0] & 0x0f));
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s\n", id_list_get(list_Progress, data[0] & 0x7f));
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
CCsetup()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
if (data[0] == 0x04)
|
|
{
|
|
OUTF("00000100 Bearer Capability\n");
|
|
data++;
|
|
BearerCap();
|
|
} else if (data[0] == 0x1e) {
|
|
OUTF("00011110 Progress Indicator\n");
|
|
ProgressIndicator();
|
|
return;
|
|
} else {
|
|
OUTF("%s FIXME\n", BitRowFill(data[0], 0xff));
|
|
}
|
|
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
Cause()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Length of Cause: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Coding: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_CodingStandard, (data[0] >> 5) & 0x03));
|
|
OUTF("%s Location: %s\n", BitRowFill(data[0], 0x0f), id_list_get(list_Location, data[0] & 0x0f));
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Cause: %s\n", BitRowFill(data[0], 0x7f), id_list_get(list_Cause, data[0] & 0x7f));
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
l2_RRclassmarkChange()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
MSClassMarkTwo();
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
if (data[0] == 0x20)
|
|
{
|
|
OUTF("00100000 Class Mark 3 [FIXME]\n");
|
|
data++;
|
|
}
|
|
}
|
|
|
|
static void
|
|
SmsProtocolDataValidity()
|
|
{
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Protocol Identifier: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
OUTF("%s Data Coding Sheme: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
data++;
|
|
}
|
|
|
|
static void
|
|
BearerCap()
|
|
{
|
|
int len;
|
|
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
len = data[0];
|
|
OUTF("%s Length: %u\n", BitRowFill(data[0], 0xff), data[0]);
|
|
if (data + len > end)
|
|
len = end - data;
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Radio Channel: %s\n", BitRowFill(data[0], 0x60), id_list_get(list_RadioChannelReq, (data[0] >> 5) & 0x03));
|
|
if ((data[0] >> 4) & 1)
|
|
OUTF("---1---- Coding Standard: reserved\n");
|
|
else
|
|
OUTF("---0---- Coding Standard: GSM\n");
|
|
if ((data[0] >> 3) & 1)
|
|
OUTF("----1--- Transfer Mode: Packet\n");
|
|
else
|
|
OUTF("----0--- Transfer Mode: Circuit\n");
|
|
|
|
OUTF("%s Transfer Capability: %s\n", BitRowFill(data[0], 0x07), id_list_get(list_TransferCap, data[0] & 0x07));
|
|
//len--;
|
|
OUTF("FIXME: Stuff missing here\n");
|
|
#if 0
|
|
if (++data >= end)
|
|
RETTRUNK();
|
|
if ((data[0] >> 6) & 1)
|
|
OUTF("-1------ Coding: octet 3 extended [FIXME]\n");
|
|
else
|
|
OUTF("-0------ Coding: octet 3 extended for inf. trans. cap\n");
|
|
|
|
/* FIXME: Stuff missing here */
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
AuthenticationRequest()
|
|
{
|
|
char rand[16 * 2 + 1];
|
|
|
|
if (data >= end)
|
|
RETTRUNK();
|
|
|
|
OUTF("%s Cipher Key Sequence Number: %u\n", BitRowFill(data[0], 0x07), data[0] & 0x07);
|
|
data++;
|
|
if (data + 16 > end)
|
|
RETTRUNK();
|
|
|
|
snprintf(rand, sizeof rand, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
|
|
OUTF("-------- RAND: %s\n", rand);
|
|
data += 16;
|
|
}
|
|
|
|
static void
|
|
AuthenticationResponse()
|
|
{
|
|
char sres[4 * 2 + 1];
|
|
|
|
if (data + 4 > end)
|
|
RETTRUNK();
|
|
snprintf(sres, sizeof sres, "%02x%02x%02x%02x", data[0], data[1], data[2], data[3]);
|
|
OUTF("-------- SRES: %s\n", sres);
|
|
data += 4;
|
|
}
|
|
|