aboutsummaryrefslogtreecommitdiff
path: root/decode/wmc.py
blob: 87d72740149b43603882202e1405835314f3a7d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#!/usr/bin/python
# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details:
#
# Copyright (C) 2011 Red Hat, Inc.
#

import binascii
import struct
import defs

def unpack(data, direction):
    # unpack the data
    if direction == defs.TO_MODEM:
        if data[:14] == "41542a574d433d":
            # remove the AT*WMC= bits, and the newline and CRC at the end
            data = data[14:]
            if data[len(data) - 2:] == "0d":
                data = data[:len(data) - 6]
    elif direction == defs.TO_HOST:
        if data[len(data) - 2:] == "7e":
            # remove HDLC terminator and CRC
            data = data[:len(data) - 6]
    else:
        raise ValueError("No data direction")

    data = binascii.unhexlify(data)

    # PPP-unescape it
    escape = False
    new_data = ""
    for i in data:
        if ord(i) == 0x7D:
            escape = True
        elif escape == True:
            new_data += chr(ord(i) ^ 0x20)
            escape = False
        else:
            new_data += i

    return new_data

def show_data(data, prefix):
    line = ""
    for i in data:
        line += " %02x" % ord(i)
    print prefix + "  Data:  %s" % line

def show_device_info(data, prefix, direction):
    if direction != defs.TO_HOST:
        return

    fmt = "<"
    fmt = fmt + "27s"  # unknown1
    fmt = fmt + "64s"  # manf
    fmt = fmt + "64s"  # model
    fmt = fmt + "64s"  # fwrev
    fmt = fmt + "64s"  # hwrev
    fmt = fmt + "64s"  # unknown2
    fmt = fmt + "64s"  # unknown3
    fmt = fmt + "10s"  # min
    fmt = fmt + "12s"  # unknown4
    fmt = fmt + "H"    # home_sid
    fmt = fmt + "6s"   # unknown5
    fmt = fmt + "H"    # eri_ver?
    fmt = fmt + "3s"   # unknown6
    fmt = fmt + "64s"  # unknown7
    fmt = fmt + "20s"  # meid
    fmt = fmt + "22s"  # imei
    fmt = fmt + "16s"  # unknown9
    fmt = fmt + "22s"  # iccid
    fmt = fmt + "4s"   # unknown10
    fmt = fmt + "16s"  # MCC
    fmt = fmt + "16s"  # MNC
    fmt = fmt + "4s"   # unknown11
    fmt = fmt + "4s"   # unknown12
    fmt = fmt + "4s"   # unknown13
    fmt = fmt + "1s"

    expected = struct.calcsize(fmt)
    if len(data) != expected:
        raise ValueError("Unexpected Info command response len (got %d expected %d)" % (len(data), expected))
    (u1, manf, model, fwrev, hwrev, u2, u3, cdmamin, u4, homesid, u5, eriver, \
        u6, u7, meid, imei, u9, iccid, u10, mcc, mnc, u11, u12, u13, u14) = struct.unpack(fmt, data)

    print prefix + "  Manf:     %s" % manf
    print prefix + "  Model:    %s" % model
    print prefix + "  FW Rev:   %s" % fwrev
    print prefix + "  HW Rev:   %s" % hwrev
    print prefix + "  MIN:      %s" % cdmamin
    print prefix + "  Home SID: %d" % homesid
    print prefix + "  ERI Ver:  %d" % eriver
    print prefix + "  MEID:     %s" % meid
    print prefix + "  IMEI:     %s" % imei
    print prefix + "  Unk9:     %s" % u9
    print prefix + "  ICCID:    %s" % iccid
    print prefix + "  MCC:      %s" % mcc
    print prefix + "  MNC:      %s" % mnc

def show_ip_info(data, prefix, direction):
    if direction != defs.TO_HOST:
        return

    fmt = "<"
    fmt = fmt + "I"   # rx_bytes
    fmt = fmt + "I"   # tx_bytes
    fmt = fmt + "8s"  # unknown3
    fmt = fmt + "B"   # unknown4
    fmt = fmt + "7s"  # unknown7
    fmt = fmt + "16s" # ip4_address
    fmt = fmt + "8s"  # netmask?
    fmt = fmt + "40s" # ip6_address

    expected = struct.calcsize(fmt)
    if len(data) != expected:
        raise ValueError("Unexpected IP Info command response len (got %d expected %d)" % (len(data), expected))
    (rxb, txb, u3, u4, u7, ip4addr, netmask, ip6addr) = struct.unpack(fmt, data)

    print prefix + "  RX Bytes: %d" % rxb
    print prefix + "  TX Bytes: %d" % txb
    print prefix + "  IP4 Addr: %s" % ip4addr
    print prefix + "  IP6 Addr: %s" % ip6addr

def get_signal(item):
    if item == 0x7D:
        return (item * -1, "(NO SIGNAL)")
    else:
        return (item * -1, "")

def show_status(data, prefix, direction):
    if direction != defs.TO_HOST:
        return

    fmt = "<"
    fmt = fmt + "B"   # unknown1
    fmt = fmt + "3s"  # unknown2
    fmt = fmt + "B"   # unknown3
    fmt = fmt + "B"   # unknown4
    fmt = fmt + "10s" # magic
    fmt = fmt + "H"   # counter1
    fmt = fmt + "H"   # counter2
    fmt = fmt + "B"   # unknown5
    fmt = fmt + "3s"  # unknown6
    fmt = fmt + "B"   # cdma1x_dbm
    fmt = fmt + "3s"  # unknown7
    fmt = fmt + "16s" # cdma_opname
    fmt = fmt + "18s" # unknown8
    fmt = fmt + "B"   # hdr_dbm
    fmt = fmt + "3s"  # unknown9
    fmt = fmt + "B"   # unknown10
    fmt = fmt + "3s"  # unknown11
    fmt = fmt + "B"   # unknown12
    fmt = fmt + "8s"  # lte_opname
    fmt = fmt + "60s" # unknown13
    fmt = fmt + "B"   # lte_dbm
    fmt = fmt + "3s"  # unknown14
    fmt = fmt + "4s"  # unknown15

    expected = struct.calcsize(fmt)
    if len(data) != expected:
        raise ValueError("Unexpected Status command response len (got %d expected %d)" % (len(data), expected))
    (u1, u2, u3, u4, magic, counter1, counter2, u5, u6, cdma_dbm, u7, cdma_opname, \
        u8, hdr_dbm, u9, u10, u11, u12, lte_opname, u13, lte_dbm, u14, u15) = struct.unpack(fmt, data)

    print prefix + "  Counter1: %s" % counter1
    print prefix + "  Counter2: %s" % counter2
    print prefix + "  CDMA dBm: %d dBm %s" % get_signal(cdma_dbm)
    print prefix + "  CDMA Op:  %s" % cdma_opname
    print prefix + "  HDR dBm:  %d dBm %s" % get_signal(hdr_dbm)
    print prefix + "  LTE Op:   %s" % lte_opname
    print prefix + "  LTE dBm:  %d dBm %s" % get_signal(lte_dbm)

def show_init(data, prefix, direction):
    show_data(data, prefix)

def show_bearer_info(data, prefix, direction):
    pass

cmds = { 0x06: ("DEVICE_INFO", show_device_info),
         0x0A: ("IP_INFO", show_ip_info),
         0x0B: ("STATUS", show_status),
         0x0D: ("INIT", show_init),
         0x4D: ("EPS_BEARER_INFO", show_bearer_info)
       }

def show(data, prefix, direction):
    if ord(data[:1]) != 0xC8:
        return

    data = data[1:]  # skip 0xC8 header
    cmdno = ord(data[:1])
    try:
        cmdinfo = cmds[cmdno]
    except KeyError:
        return
    data = data[1:]  # skip cmdno

    print prefix + "WMC Packet:"
    print prefix + "  Cmd:    0x%02x (%s)" % (cmdno, cmdinfo[0])
    cmdinfo[1](data, prefix, direction)
    print ""

def get_funcs():
    return (unpack, show)