FreeCalypso > hg > freecalypso-sw
comparison rvinterf/lowlevel/format_g23.c @ 327:05874f1ddacb
rvinterf & rvtdump: new decoding of G23/GPF packets
| author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
|---|---|
| date | Sun, 20 Apr 2014 20:39:53 +0000 |
| parents | 2f285f20d617 |
| children |
comparison
equal
deleted
inserted
replaced
| 326:7e878e6b9cf7 | 327:05874f1ddacb |
|---|---|
| 1 /* | 1 /* |
| 2 * This module implements the decoding of G23 trace packets into | 2 * This module implements the decoding of G23 trace packets into |
| 3 * human-readable form. Because I have not yet reached the point | 3 * human-readable form - or more precisely, traces, system primitives |
| 4 * of integrating the target-side code that generates these packets, | 4 * and other packets that can be emitted through GPF on targets. |
| 5 * I do not yet have the proper understanding of their format. | 5 * The decoding is based on my (Space Falcon's) understanding |
| 6 * Therefore, the current decoding logic implemented here is based | 6 * of the packet format, which is in turn based on the GPF sources |
| 7 * on a heuristic examination of what the packets look like to an | 7 * available to us, now integrated under gsm-fw/gpf. |
| 8 * uninitiated eye. | |
| 9 */ | 8 */ |
| 10 | 9 |
| 11 #include <sys/types.h> | 10 #include <sys/types.h> |
| 11 #include <ctype.h> | |
| 12 #include <stdio.h> | 12 #include <stdio.h> |
| 13 #include <string.h> | 13 #include <string.h> |
| 14 #include <strings.h> | 14 #include <strings.h> |
| 15 #include "../include/pktmux.h" | 15 #include "../include/pktmux.h" |
| 16 #include "../include/limits.h" | 16 #include "../include/limits.h" |
| 17 | 17 |
| 18 extern u_char rxpkt[]; | 18 extern u_char rxpkt[]; |
| 19 extern size_t rxpkt_len; | 19 extern size_t rxpkt_len; |
| 20 extern char fmtbuf[]; | |
| 21 | |
| 22 static char *fmtbuf_ptr; | |
| 20 | 23 |
| 21 static int | 24 static int |
| 22 is_well_formed() | 25 basic_checks() |
| 23 { | 26 { |
| 24 int i, c; | 27 int i, c; |
| 25 | 28 |
| 26 if (rxpkt_len < 17) | 29 if (rxpkt_len < 17) |
| 27 return(0); | 30 return(0); |
| 31 /* check version bits in the header byte */ | |
| 32 if ((rxpkt[1] & 0xC0) != 0x80) | |
| 33 return(0); | |
| 34 /* check the length */ | |
| 35 c = rxpkt[2] | rxpkt[3] << 8; | |
| 36 if (c + 4 != rxpkt_len) | |
| 37 return(0); | |
| 38 /* ensure that the "from" and "to" are printable ASCII */ | |
| 28 for (i = 8; i < 16; i++) { | 39 for (i = 8; i < 16; i++) { |
| 29 c = rxpkt[i]; | 40 c = rxpkt[i]; |
| 30 if (c < ' ' || c > '~') | 41 if (c < ' ' || c > '~') |
| 31 return(0); | 42 return(0); |
| 32 } | 43 } |
| 44 /* basic checks pass */ | |
| 33 return(1); | 45 return(1); |
| 34 } | 46 } |
| 35 | 47 |
| 36 static void | 48 static int |
| 37 print_well_formed() | 49 psprim_extra_checks() |
| 38 { | 50 { |
| 39 char buf[MAX_PKT_FROM_TARGET*4]; | |
| 40 int i, c; | 51 int i, c; |
| 52 | |
| 53 if (rxpkt_len < 24) | |
| 54 return(0); | |
| 55 /* "original rcvr" field needs to be printable ASCII */ | |
| 56 for (i = 16; i < 20; i++) { | |
| 57 c = rxpkt[i]; | |
| 58 if (c < ' ' || c > '~') | |
| 59 return(0); | |
| 60 } | |
| 61 /* checks pass */ | |
| 62 return(1); | |
| 63 } | |
| 64 | |
| 65 static void | |
| 66 print_malformed() | |
| 67 { | |
| 68 int i; | |
| 41 char *dp; | 69 char *dp; |
| 42 | 70 |
| 43 dp = buf; | 71 dp = fmtbuf; |
| 44 strcpy(dp, "G23:"); | |
| 45 dp += 4; | |
| 46 for (i = 1; i <= 7; i++) { | |
| 47 sprintf(dp, " %02X", rxpkt[i]); | |
| 48 dp += 3; | |
| 49 } | |
| 50 sprintf(dp, " \"%.4s\" \"%.4s\" ", rxpkt+8, rxpkt+12); | |
| 51 dp += 15; | |
| 52 i = 16; | |
| 53 if (rxpkt[i] < 0x20) { | |
| 54 sprintf(dp, "%02X ", rxpkt[i]); | |
| 55 dp += 3; | |
| 56 i++; | |
| 57 } | |
| 58 if (rxpkt_len - i == 5 && rxpkt[i] == '%' && | |
| 59 !rxpkt[i+3] && !rxpkt[i+4]) { | |
| 60 sprintf(dp, "%d", rxpkt[i+2] << 8 | rxpkt[i+1]); | |
| 61 output_line(buf); | |
| 62 return; | |
| 63 } | |
| 64 *dp++ = '\"'; | |
| 65 for (; i < rxpkt_len; i++) { | |
| 66 c = rxpkt[i]; | |
| 67 if (c & 0x80) { | |
| 68 *dp++ = 'M'; | |
| 69 *dp++ = '-'; | |
| 70 c &= 0x7F; | |
| 71 } | |
| 72 if (c < 0x20) { | |
| 73 *dp++ = '^'; | |
| 74 *dp++ = c + '@'; | |
| 75 } else if (c == 0x7F) { | |
| 76 *dp++ = '^'; | |
| 77 *dp++ = '?'; | |
| 78 } else | |
| 79 *dp++ = c; | |
| 80 } | |
| 81 *dp++ = '\"'; | |
| 82 *dp = '\0'; | |
| 83 output_line(buf); | |
| 84 } | |
| 85 | |
| 86 static void | |
| 87 print_malformed() | |
| 88 { | |
| 89 char buf[MAX_PKT_FROM_TARGET*3+6]; | |
| 90 int i; | |
| 91 char *dp; | |
| 92 | |
| 93 dp = buf; | |
| 94 strcpy(dp, "G23 UNK:"); | 72 strcpy(dp, "G23 UNK:"); |
| 95 dp += 8; | 73 dp += 8; |
| 96 for (i = 1; i < rxpkt_len; i++) { | 74 for (i = 1; i < rxpkt_len; i++) { |
| 97 sprintf(dp, " %02X", rxpkt[i]); | 75 sprintf(dp, " %02X", rxpkt[i]); |
| 98 dp += 3; | 76 dp += 3; |
| 99 } | 77 } |
| 100 *dp = '\0'; | 78 *dp = '\0'; |
| 101 output_line(buf); | 79 output_line(fmtbuf); |
| 80 } | |
| 81 | |
| 82 static int | |
| 83 entity_name_well_formed(p) | |
| 84 char *p; | |
| 85 { | |
| 86 int i, len; | |
| 87 | |
| 88 if (!isupper(p[0])) | |
| 89 return(0); | |
| 90 for (i = 0; i < 4; i++) | |
| 91 if (!isalnum(p[i])) | |
| 92 break; | |
| 93 len = i; | |
| 94 for (; i < 4; i++) | |
| 95 if (p[i] != ' ') | |
| 96 return(0); | |
| 97 return(len); | |
| 98 } | |
| 99 | |
| 100 static void | |
| 101 print_entity_name(raw) | |
| 102 char *raw; | |
| 103 { | |
| 104 int len; | |
| 105 | |
| 106 len = entity_name_well_formed(raw); | |
| 107 if (len) | |
| 108 sprintf(fmtbuf_ptr, "%.*s", len, raw); | |
| 109 else | |
| 110 sprintf(fmtbuf_ptr, "\"%.4s\"", raw); | |
| 111 fmtbuf_ptr = index(fmtbuf_ptr, '\0'); | |
| 112 } | |
| 113 | |
| 114 static void | |
| 115 print_common_hdr(typestr) | |
| 116 char *typestr; | |
| 117 { | |
| 118 sprintf(fmtbuf, "G23 %s id=%02X ts=%02X%02X%02X%02X ", typestr, | |
| 119 rxpkt[1], rxpkt[7], rxpkt[6], rxpkt[5], rxpkt[4]); | |
| 120 fmtbuf_ptr = index(fmtbuf, '\0'); | |
| 121 print_entity_name(rxpkt + 8); | |
| 122 *fmtbuf_ptr++ = '-'; | |
| 123 *fmtbuf_ptr++ = '>'; | |
| 124 print_entity_name(rxpkt + 12); | |
| 125 *fmtbuf_ptr++ = ' '; | |
| 126 } | |
| 127 | |
| 128 static void | |
| 129 format_text(start_off) | |
| 130 { | |
| 131 int i, c; | |
| 132 | |
| 133 *fmtbuf_ptr++ = '\"'; | |
| 134 for (i = start_off; i < rxpkt_len; i++) { | |
| 135 c = rxpkt[i]; | |
| 136 if (c & 0x80) { | |
| 137 *fmtbuf_ptr++ = 'M'; | |
| 138 *fmtbuf_ptr++ = '-'; | |
| 139 c &= 0x7F; | |
| 140 } | |
| 141 if (c < 0x20) { | |
| 142 *fmtbuf_ptr++ = '^'; | |
| 143 *fmtbuf_ptr++ = c + '@'; | |
| 144 } else if (c == 0x7F) { | |
| 145 *fmtbuf_ptr++ = '^'; | |
| 146 *fmtbuf_ptr++ = '?'; | |
| 147 } else | |
| 148 *fmtbuf_ptr++ = c; | |
| 149 } | |
| 150 *fmtbuf_ptr++ = '\"'; | |
| 151 *fmtbuf_ptr = '\0'; | |
| 152 output_line(fmtbuf); | |
| 153 } | |
| 154 | |
| 155 static void | |
| 156 format_compressed_trace(start_off) | |
| 157 { | |
| 158 int i; | |
| 159 | |
| 160 i = start_off + 1; | |
| 161 sprintf(fmtbuf_ptr, "%d", rxpkt[i+1] << 8 | rxpkt[i]); | |
| 162 fmtbuf_ptr = index(fmtbuf_ptr, '\0'); | |
| 163 i += 4; | |
| 164 for (; i < rxpkt_len; i++) { | |
| 165 sprintf(fmtbuf_ptr, " %02X", rxpkt[i]); | |
| 166 fmtbuf_ptr += 3; | |
| 167 } | |
| 168 *fmtbuf_ptr = '\0'; | |
| 169 output_line(fmtbuf); | |
| 170 } | |
| 171 | |
| 172 static void | |
| 173 format_trace() | |
| 174 { | |
| 175 int i; | |
| 176 | |
| 177 i = 16; | |
| 178 if (rxpkt[i] < 0x20) { | |
| 179 sprintf(fmtbuf_ptr, "tc=%02X ", rxpkt[i]); | |
| 180 fmtbuf_ptr += 6; | |
| 181 i++; | |
| 182 } | |
| 183 if (rxpkt_len - i >= 5 && rxpkt[i] == '%' && | |
| 184 !rxpkt[i+3] && !rxpkt[i+4]) | |
| 185 format_compressed_trace(i); | |
| 186 else | |
| 187 format_text(i); | |
| 188 } | |
| 189 | |
| 190 static void | |
| 191 format_psprim() | |
| 192 { | |
| 193 int i; | |
| 194 | |
| 195 /* original destination */ | |
| 196 *fmtbuf_ptr++ = '('; | |
| 197 print_entity_name(rxpkt + 16); | |
| 198 *fmtbuf_ptr++ = ')'; | |
| 199 /* opcode */ | |
| 200 sprintf(fmtbuf_ptr, " %02X%02X%02X%02X", | |
| 201 rxpkt[23], rxpkt[22], rxpkt[21], rxpkt[20]); | |
| 202 fmtbuf_ptr += 9; | |
| 203 for (i = 24; i < rxpkt_len; i++) { | |
| 204 sprintf(fmtbuf_ptr, " %02X", rxpkt[i]); | |
| 205 fmtbuf_ptr += 3; | |
| 206 } | |
| 207 *fmtbuf_ptr = '\0'; | |
| 208 output_line(fmtbuf); | |
| 102 } | 209 } |
| 103 | 210 |
| 104 void | 211 void |
| 105 print_g23_trace() | 212 print_g23_trace() |
| 106 { | 213 { |
| 107 if (is_well_formed()) | 214 if (!basic_checks()) { |
| 108 print_well_formed(); | |
| 109 else | |
| 110 print_malformed(); | 215 print_malformed(); |
| 111 } | 216 return; |
| 217 } | |
| 218 /* dispatch by type */ | |
| 219 switch (rxpkt[1] & 0x30) { | |
| 220 case 0x10: | |
| 221 /* PS primitive */ | |
| 222 if (psprim_extra_checks()) { | |
| 223 print_common_hdr("PSprim"); | |
| 224 format_psprim(); | |
| 225 } else | |
| 226 print_malformed(); | |
| 227 return; | |
| 228 case 0x20: | |
| 229 /* trace */ | |
| 230 print_common_hdr("trace"); | |
| 231 format_trace(); | |
| 232 return; | |
| 233 case 0x30: | |
| 234 /* system primitive */ | |
| 235 print_common_hdr("sysprim"); | |
| 236 format_text(16); | |
| 237 return; | |
| 238 default: | |
| 239 print_malformed(); | |
| 240 } | |
| 241 } |
