summaryrefslogtreecommitdiffabout
path: root/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
Side-by-side diff
Diffstat (limited to 'gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c b/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
new file mode 100644
index 0000000..44db64b
--- a/dev/null
+++ b/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
@@ -0,0 +1,416 @@
+/**
+ * Simple GSM frame decoder
+ * wumpus 2003 -- www.blacksphere.tk
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#include "wmx-util.h"
+#include "wmx-gsm.h"
+
+/* Administrative */
+GSMDecoder *GSMDecoder_new()
+{
+ GSMDecoder *self;
+
+ self = malloc(sizeof(GSMDecoder));
+ self->xmlout = NULL;
+
+ return self;
+}
+
+/**
+ * Set 'sniffer' XML output stream
+ */
+void GSMDecoder_xmlout(GSMDecoder *self, FILE *f)
+{
+ self->xmlout = f;
+ if(self->xmlout) {
+ /* Open XML doc */
+ fprintf(self->xmlout,"<?xml version=\"1.0\"?>\n");
+ fprintf(self->xmlout,"<dump>\n");
+ }
+}
+
+void GSMDecoder_free(GSMDecoder *self)
+{
+ if(self->xmlout) {
+ fprintf(self->xmlout,"</dump>\n");
+ fclose(self->xmlout);
+ }
+ free(self);
+}
+
+char *GSM_protocols[]={
+/*0*/ "Group call control",
+/*1*/ "Broadcast call control",
+/*2*/ "PDSS1",
+/*3*/ "Call Control; call related SS messages (TS 24.008)",
+/*4*/ "PDSS2",
+/*5*/ "Mobility Management messages (TS 24.008)",
+/*6*/ "Radio Resources management messages (GSM 04.18)",
+/*7*/ "RFU",
+/*8*/ "GPRS mobility management messages",
+/*9*/ "SMS messages (GSM 04.11)",
+/*A*/ "GPRS session management messages",
+/*B*/ "Non call related SS messages (GSM 04.80)",
+/*C*/ "Location services",
+/*D*/ "RFU",
+/*E*/ "Reserved for extension of the PD to one octet length",
+/*F*/ "Reserved for tests procedures described in GSM 11.10"
+};
+
+typedef struct GSMpackettypestruct {
+ int id;
+ char *section;
+ char *description;
+} GSMpackettype;
+
+/* Include the data */
+GSMpackettype GSM_RR_packettypes[] = {
+#include "type-rr.h"
+};
+GSMpackettype GSM_MM_packettypes[] = {
+#include "type-mm.h"
+};
+GSMpackettype GSM_CC_packettypes[] = {
+#include "type-cc.h"
+};
+GSMpackettype GSM_SS_packettypes[] = {
+#include "type-ss.h"
+};
+GSMpackettype GSM_SMS_packettypes[] = {
+#include "type-sms.h"
+};
+
+GSMpackettype *GSMpackettype_lookup(GSMpackettype list[], int id)
+{
+ GSMpackettype *ptr = list;
+
+ while(ptr->id != -1 && ptr->id != id) ptr++;
+ if(ptr->id == -1) {
+ return NULL;
+ } else {
+ return ptr;
+ }
+}
+
+/* disassemble L3 packet -- GSM 04.06
+tx=0 Network to MS
+tx=1 MS to Network
+*/
+void GSMDecoder_L3packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
+{
+ int proto,type;
+ GSMpackettype *ptype;
+
+ dumpraw("Inform", buffer, length);
+ printf(" ");
+ if(length < 2) return;
+
+ /* Attempt at decoding first byte
+ -- protocol discriminator
+ */
+ proto = buffer[0]&0xF;
+ printf("\n %s ", GSM_protocols[proto]);
+
+ switch(proto) {
+ case 0x3: /* CC */
+ type = buffer[1]&0x3F;
+ ptype = GSMpackettype_lookup(GSM_CC_packettypes, type);
+ if (ptype == NULL) {
+ printf("\n Unknown %02X", type);
+ } else {
+ printf("\n %s (%s)", ptype->description, ptype->section);
+ }
+ break;
+ case 0x5: /* MM */
+ type = buffer[1]&0x3F;
+ ptype = GSMpackettype_lookup(GSM_MM_packettypes, type);
+ if (ptype == NULL) {
+ printf("\n Unknown %02X", type);
+ } else {
+ printf("\n %s (%s)", ptype->description, ptype->section);
+ }
+ break;
+ case 0x6: /* RR */
+ if (buffer[0]>>4) {
+ printf("\n RR:Invalid Skip Indicator");
+ return;
+ }
+ type = buffer[1];
+ ptype = GSMpackettype_lookup(GSM_RR_packettypes, type);
+ if (ptype == NULL) {
+ printf("\n Unknown %02X", type);
+ } else {
+ printf("\n %s (%s)", ptype->description, ptype->section);
+ }
+ break;
+ case 0x9: /* SMS */
+ type = buffer[1]&0x3F;
+ ptype = GSMpackettype_lookup(GSM_SMS_packettypes, type);
+ if (ptype == NULL) {
+ printf("\n Unknown %02X", type);
+ } else {
+ printf("\n %s (%s)", ptype->description, ptype->section);
+ }
+ break;
+ case 0xB: /* SS */
+ if (buffer[1]&0x80) {
+ printf("\n SS:Invalid Message Type");
+ return;
+ }
+ type = buffer[1]&0x3F;
+ ptype = GSMpackettype_lookup(GSM_SS_packettypes, type);
+ if (ptype == NULL) {
+ printf("\n Unknown %02X", type);
+ } else {
+ printf("\n %s (%s)", ptype->description, ptype->section);
+ }
+ break;
+ }
+}
+
+static void GSMDecoder_l1xml_open(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
+{
+ unsigned int x;
+
+ if(self->xmlout) {
+ fprintf(self->xmlout, "<l1 ");
+ fprintf(self->xmlout, "direction=\"%s\" ", l1->tx==GSMDECODER_SEND?"up":"down");
+ fprintf(self->xmlout, "logicalchannel=\"%i\" ", l1->ch);
+ if(l1->tx == GSMDECODER_RECEIVE) {
+ fprintf(self->xmlout, "physicalchannel=\"%i\" ", l1->arfcn);
+ fprintf(self->xmlout, "sequence=\"%u\" ", l1->seq);
+ fprintf(self->xmlout, "error=\"%i\" ", l1->err);
+ fprintf(self->xmlout, "timeshift=\"%i\" ", l1->timeshift);
+ fprintf(self->xmlout, "bsic=\"%i\" ", l1->bsic);
+ fprintf(self->xmlout, "data=\"");
+ for(x=0; x<length; x++) {
+ fprintf(self->xmlout, "%02X", buffer[x]);
+ }
+ fprintf(self->xmlout, "\" ");
+ }
+ fprintf(self->xmlout, ">\n");
+ }
+}
+
+static void GSMDecoder_l1xml_close(GSMDecoder *self)
+{
+ if(self->xmlout) fprintf(self->xmlout, "</l1>\n");
+}
+
+/* disassemble L2 pseudo length header packet -- GSM 04.06
+ tx=0 Network to MS
+ tx=1 MS to Network
+ write XML stream
+*/
+void GSMDecoder_L2short_packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
+{
+ size_t ptr,usedlength, x;
+
+ GSMDecoder_l1xml_open(self, l1, buffer, length);
+
+ if(length<1) {
+ /* too small to contain 1 header byte */
+ printf("L2 packet too small\n");
+ GSMDecoder_l1xml_close(self);
+ return;
+ }
+ ptr = 0;
+ //printf("L2 packet\n");
+
+ /* dump Length Indicator field */
+ usedlength = buffer[ptr]>>2;
+ if((buffer[ptr]&3) != 1) {
+ dumpraw("ErrPacket", buffer, length);
+ printf(" Invalid pseudo length byte\n");
+ GSMDecoder_l1xml_close(self);
+ return;
+ }
+ printf("Length : used=%i ID=%i\n",
+ usedlength,
+ (buffer[ptr]>>0)&3);
+ ptr++;
+ /* dump Information */
+ printf("Inform : ");
+ if((ptr+usedlength) > length) {
+ printf("Invalid used length\n");
+ }
+ if(self->xmlout) {
+ fprintf(self->xmlout, "<l2 ");
+ fprintf(self->xmlout, "data=\"");
+ for(x=0; x<usedlength; x++) fprintf(self->xmlout, "%02X", buffer[ptr+x]);
+ fprintf(self->xmlout, "\" ");
+ /* Rest octets */
+ fprintf(self->xmlout, "rest=\"");
+ for(x=(ptr+usedlength); x<length; x++) fprintf(self->xmlout, "%02X", buffer[x]);
+ fprintf(self->xmlout, "\" ");
+ fprintf(self->xmlout, ">\n");
+ }
+ GSMDecoder_L3packet(self, l1, &buffer[ptr], usedlength);
+ if(self->xmlout) fprintf(self->xmlout, "</l2>\n");
+ //dumpraw("Inform", &buffer[ptr], usedlength);
+ //printf("\n");
+ GSMDecoder_l1xml_close(self);
+}
+
+#define TYPE_I 0x01 /* Information */
+#define TYPE_S 0x02 /* Supervisory */
+#define TYPE_U 0x03 /* Unnumbered */
+
+/* disassemble L2 packet -- GSM 04.06
+tx=0 Network to MS
+tx=1 MS to Network
+*/
+void GSMDecoder_L2packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
+{
+ size_t ptr,usedlength,x;
+ int more;
+ int type;
+ char temp[80];
+
+ GSMDecoder_l1xml_open(self, l1, buffer, length);
+
+ if(length<5) {
+ /* too small to contain 3 header bytes plus 20 data bytes */
+ printf("L2 packet too small\n");
+ GSMDecoder_l1xml_close(self);
+ return;
+ }
+ ptr = 0;
+ //printf("L2 packet\n");
+ /* dump Address field */
+ printf("Address: LPD=%i SAPI=%i C/R=%i EA=%i\n",
+ (buffer[ptr]>>5)&3,
+ (buffer[ptr]>>2)&7,
+ (buffer[ptr]>>1)&1,
+ (buffer[ptr]>>0)&1);
+ /* skip next address field bytes */
+ while((buffer[ptr]&1)==0) ptr++;
+ ptr++;
+ /* dump Control field */
+
+ type = TYPE_I;
+ // if(!(buffer[ptr]&1)) type = TYPE_I;
+ if((buffer[ptr]&1) && !(buffer[ptr]&2)) type = TYPE_S;
+ if((buffer[ptr]&1) && (buffer[ptr]&2)) type = TYPE_U;
+ switch(type) {
+ case TYPE_I:
+ printf("Control: I TXSeq=%i P=%i RXSeq=%i\n",
+ (buffer[ptr]>>5)&7,
+ (buffer[ptr]>>4)&1,
+ (buffer[ptr]>>1)&7);
+ break;
+ case TYPE_S: {
+ char *desc = "Unknown";
+ x = (buffer[ptr]>>2)&3;
+ switch(x) {
+ case 0: /* 00 */ desc="RR (Receive Ready)"; break; /* ALSO acknowledgement */
+ case 1: /* 01 */ desc="RNR (Receive Not Ready)"; break;
+ case 2: /* 10 */ desc="REJ (Reject)"; break;
+ }
+ printf("Control: S TXSeq=%i P/F=%i S=%i %s\n",
+ (buffer[ptr]>>5)&7,
+ (buffer[ptr]>>4)&1,
+ x, desc);
+ } break;
+ case TYPE_U: {
+ char *desc = "Unknown";
+ x = (((buffer[ptr]>>5)&7)<<2) | ((buffer[ptr]>>2)&3);
+ binstr(temp, x, 5);
+ switch(x) {
+ case 0: /* 00000 */ desc = "UI (Unnumbered information)"; break;
+ case 3: /* 00011 */ desc = "DM (Disconnect mode)"; break;
+ case 7: /* 00111 */ desc = "SABM (Set asynchronous balanced mode)"; break;
+ case 8: /* 01000 */ desc = "DISC (Disconnect)"; break;
+ case 12:/* 01100 */ desc = "UA (Unnumbered acknowledge)"; break;
+ }
+
+ printf("Control: U U=%s %s P/F=%i\n",
+ temp, desc,
+ (buffer[ptr]>>4)&1);
+ } break;
+ }
+ ptr++;
+ /* dump Length Indicator field */
+ usedlength = buffer[ptr]>>2;
+ more = (buffer[ptr]>>1)&1; /* more to go */
+ printf("Length : used=%i M=%i EL=%i\n",
+ usedlength, more,
+ (buffer[ptr]>>0)&1);
+ while((buffer[ptr]&1)==0) ptr++;
+ ptr++;
+ /* dump Information */
+ printf("Inform : ");
+ if((ptr+usedlength) > length) {
+ printf("Invalid used length\n");
+ }
+ /*
+ for(x=0; x<usedlength; x++) {
+ printf("%02x ",buffer[ptr]);
+ ptr++;
+ }
+ */
+ if(self->xmlout) {
+ char *desc;
+ fprintf(self->xmlout, "<l2 ");
+ switch(type) {
+ case TYPE_I:
+ fprintf(self->xmlout, "type=\"I\" ");
+ fprintf(self->xmlout, "txseq=\"%i\" p=\"%i\" rxseq=\"%i\" ",
+ (buffer[ptr]>>5)&7,
+ (buffer[ptr]>>4)&1,
+ (buffer[ptr]>>1)&7);
+ break;
+ case TYPE_S:
+ fprintf(self->xmlout, "type=\"S\" ");
+ desc = "Unknown";
+ x = (buffer[ptr]>>2)&3;
+ switch(x) {
+ case 0: /* 00 */ desc="RR"; break; /* ALSO acknowledgement */
+ case 1: /* 01 */ desc="RNR"; break;
+ case 2: /* 10 */ desc="REJ"; break;
+ }
+ fprintf(self->xmlout, "subtype=\"%s\" rxseq=\"%i\" p=\"%i\" ",
+ desc,
+ (buffer[ptr]>>5)&7,
+ (buffer[ptr]>>4)&1);
+ break;
+ case TYPE_U:
+ fprintf(self->xmlout, "type=\"U\" ");
+ desc = "Unknown";
+ x = (((buffer[ptr]>>5)&7)<<2) | ((buffer[ptr]>>2)&3);
+ switch(x) {
+ case 0: /* 00000 */ desc = "UI"; break;
+ case 3: /* 00011 */ desc = "DM"; break;
+ case 7: /* 00111 */ desc = "SABM"; break;
+ case 8: /* 01000 */ desc = "DISC"; break;
+ case 12:/* 01100 */ desc = "UA"; break;
+ }
+
+ fprintf(self->xmlout, "subtype=\"%s\" p=\"%i\" ",
+ desc,
+ (buffer[ptr]>>4)&1);
+ break;
+ default:
+ fprintf(self->xmlout, "type=\"Unknown\" ");
+ }
+ fprintf(self->xmlout, "data=\"");
+ for(x=0; x<usedlength; x++) fprintf(self->xmlout, "%02X", buffer[ptr+x]);
+ fprintf(self->xmlout, "\" ");
+ fprintf(self->xmlout, ">\n");
+ }
+ GSMDecoder_L3packet(self, l1, &buffer[ptr], usedlength);
+ if(self->xmlout) fprintf(self->xmlout, "</l2>\n");
+ GSMDecoder_l1xml_close(self);
+ //dumpraw("Inform", );
+ //printf("\n");
+}
+
+/* How should editor hadle tabs in this file? Add editor commands here.
+ * vim: noexpandtab sw=8 ts=8 sts=8:
+ */