def pretty(self):
     str= "IME: "+self._pretty_header()+" "
     for block in xrange(len(self.descrambled)):
         b=self.descrambled[block]
         if len(b)==31:
             (errs,foo)=nrepair(self.poly,b)
             res=ndivide(self.poly,b)
             parity=(foo).count('1') % 2
             str+="{%s %s/%04d E%s P%d}"%(b[:21],b[21:31],res,("0","1","2","-")[errs],parity)
         elif len(b)==32:
             (errs,foo)=nrepair(self.poly,b[:31])
             res=ndivide(self.poly,b[:31])
             parity=(foo+b[31]).count('1') % 2
             str+="{%s %s %s/%04d E%s P%d}"%(b[:21],b[21:31],b[31],res,("0","1","2","-")[errs],parity)
         else:
             str+="length=%d?"%len(b)
     str+=self._pretty_trailer()
     return str
示例#2
0
 def pretty(self):
     str = "IME: " + self._pretty_header() + " "
     for block in xrange(len(self.descrambled)):
         b = self.descrambled[block]
         if len(b) == 31:
             (errs, foo) = nrepair(self.poly, b)
             res = ndivide(self.poly, b)
             parity = (foo).count('1') % 2
             str += "{%s %s/%04d E%s P%d}" % (b[:21], b[21:31], res,
                                              ("0", "1", "2",
                                               "-")[errs], parity)
         elif len(b) == 32:
             (errs, foo) = nrepair(self.poly, b[:31])
             res = ndivide(self.poly, b[:31])
             parity = (foo + b[31]).count('1') % 2
             str += "{%s %s %s/%04d E%s P%d}" % (
                 b[:21], b[21:31], b[31], res,
                 ("0", "1", "2", "-")[errs], parity)
         else:
             str += "length=%d?" % len(b)
     str += self._pretty_trailer()
     return str
示例#3
0
    def __init__(self, imsg):
        self.__dict__ = copy.deepcopy(imsg.__dict__)
        if self.msgtype == "MS":
            poly = messaging_bch_poly
        elif self.msgtype == "RA":
            poly = ringalert_bch_poly
        elif self.msgtype == "BC":
            poly = ringalert_bch_poly
        elif self.msgtype == "DA":
            poly = acch_bch_poly
        else:
            raise ParserError("unknown Iridium message type")
        self.bitstream_messaging = ""

        self.bitstream_bch = ""
        self.oddbits = ""
        self.fixederrs = 0
        self.bch = []
        for block in self.descrambled:
            if len(block) != 32 and len(block) != 31:
                raise ParserError("unknown BCH block len:%d" % len(block))
            if len(block) == 32:
                parity = block[31]
            bits = block[:31]
            result = ndivide(poly, bits)
            errs = 0
            if result != 0:
                (errs, bits) = nrepair(poly, bits)
                if errs > 0:
                    self.fixederrs += 1
                if (errs < 0):
                    self._new_error("BCH decode failed")
            if len(block) == 32:
                parity = (bits + parity).count('1') % 2
            elif len(block) == 31:
                parity = (bits).count('1') % 2


#            if parity==1: raise ParserError("Parity error")
            self.bch.append((result, errs, parity))
            self.bitstream_bch += block[:21]
            self.bitstream_messaging += block[1:21]
            self.oddbits += block[0]
        if len(self.bitstream_bch) == 0:
            self._new_error("No data to descramble")
示例#4
0
    def __init__(self,imsg):
        self.__dict__=copy.deepcopy(imsg.__dict__)
        if self.msgtype == "MS":
            poly=messaging_bch_poly
        elif self.msgtype == "RA":
            poly=ringalert_bch_poly
        elif self.msgtype == "BC":
            poly=ringalert_bch_poly
        elif self.msgtype == "DA":
            poly=acch_bch_poly
        else:
            raise ParserError("unknown Iridium message type")
        self.bitstream_messaging=""

        self.bitstream_bch=""
        self.oddbits=""
        self.fixederrs=0
        self.bch=[]
        for block in self.descrambled:
            if len(block)!=32 and len(block)!=31:
                raise ParserError("unknown BCH block len:%d"%len(block))
            if len(block)==32:
                parity=block[31]
            bits=block[:31]
            result=ndivide(poly,bits)
            errs=0
            if result!=0:
                (errs,bits)=nrepair(poly, bits)
                if errs>0:
                    self.fixederrs+=1
                if(errs<0):
                    self._new_error("BCH decode failed")
            if len(block)==32:
                parity=(bits+parity).count('1') % 2
            elif len(block)==31:
                parity=(bits).count('1') % 2
#            if parity==1: raise ParserError("Parity error")
            self.bch.append((result,errs,parity))
            self.bitstream_bch+=block[:21]
            self.bitstream_messaging+=block[1:21]
            self.oddbits+=block[0]
        if len(self.bitstream_bch)==0:
            self._new_error("No data to descramble")
示例#5
0
    def __init__(self, msg):
        self.__dict__ = copy.deepcopy(msg.__dict__)
        data = self.bitstream_raw[len(iridium_access):]

        # Try to detect packet type
        if data[:32] == header_messaging:
            self.msgtype = "MS"
        elif 1626229167 < self.frequency < 1626312500:
            self.msgtype = "RA"
        elif len(
                data
        ) > 64:  # XXX: heuristic based on LCW / first BCH block, can we do better?
            (o_lcw1, o_lcw2, o_lcw3) = de_interleave_lcw(data[:46])
            (e1, lcw1, bch) = bch_repair(29, o_lcw1)
            (e2, lcw2,
             bch) = bch_repair(465,
                               o_lcw2 + '0')  # One bit missing, so we guess
            if (e2 == 1):  # Maybe the other one...
                (e2, lcw2, bch) = bch_repair(465, o_lcw2 + '1')
            (e3, lcw3, bch) = bch_repair(41, o_lcw3)
            #            if e1>=0 and e2>=0 and e3>=0: # Valid LCW
            if e1 == 0 and e2 == 0 and e3 == 0:  # GOOD LCW
                self.msgtype = "DA"
            elif len(data) > 6 + 64 and ndivide(
                    ringalert_bch_poly,
                    de_interleave(data[6:6 + 64])[0][:31]) == 0:
                self.msgtype = "BC"
            else:
                raise ParserError("unknown Iridium message type")
        else:
            raise ParserError("Iridium message too short")

        if self.msgtype == "MS":
            hdrlen = 32
            self.header = data[:hdrlen]
            self.descrambled = []
            (blocks, self.descramble_extra) = slice_extra(data[hdrlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "RA":
            firstlen = 3 * 32
            if len(data) < firstlen:
                self._new_error("No data to descramble")
            self.header = ""
            self.descrambled = de_interleave3(data[:firstlen])
            (blocks, self.descramble_extra) = slice_extra(data[firstlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "BC":
            hdrlen = 6
            self.header = data[:hdrlen]
            self.descrambled = []

            (blocks, self.descramble_extra) = slice_extra(data[hdrlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "DA":
            lcwlen = 46
            (o_lcw1, o_lcw2, o_lcw3) = de_interleave_lcw(data[:lcwlen])
            (e1, self.lcw1, bch) = bch_repair(29, o_lcw1)
            (e2, self.lcw2,
             bch) = bch_repair(465, o_lcw2 + '0')  # One bit error expected
            if e2 == 1:
                (e2, self.lcw2,
                 bch) = bch_repair(465, o_lcw2 + '1')  # Other bit flip?
            (e3, self.lcw3, bch) = bch_repair(41, o_lcw3)
            self.ft = int(self.lcw1, 2)  # Frame type
            if e1 < 0 or e2 < 0 or e3 < 0:
                self._new_error("LCW decode failed")
                self.header = "LCW(%s %s/%02d E%d,%s %sx/%03d E%d,%s %s/%02d E%d)" % (
                    o_ft[:3], o_ft[3:], ndivide(29, o_ft), e1, o_lcw2[:6],
                    o_lcw2[6:], ndivide(465, o_lcw2 + '0'), e2, o_lcw3[:21],
                    o_lcw3[21:], ndivide(41, o_lcw3), e3)
            else:
                self.header = "LCW(%d,%s,%s E%d)" % (self.ft, self.lcw2,
                                                     self.lcw3, e1 + e2 + e3)
            self.descrambled = []
            data = data[lcwlen:]

            def symbol_reverse(bits):
                r = ''
                for symbol in grouped(bits, 2):
                    r += symbol[1] + symbol[0]
                return r

            if self.ft <= 2 and len(data) < 312:
                self._new_error("Not enough data in data packet")
            if self.ft == 0:  # Voice
                self.msgtype = "VO"
                self.voice = data[:312]
                self.descramble_extra = data[312:]
            elif self.ft == 1:  # IP via PPP
                self.msgtype = "IP"
                for x in slice(symbol_reverse(data[:312]), 8):
                    self.descrambled += [x[::-1]]
                self.descramble_extra = data[312:]
            elif self.ft == 2:  # DAta (SBD)
                self.descramble_extra = data[124 * 2 + 64:]
                data = data[:124 * 2 + 64]
                blocks = slice(data, 124)
                end = blocks.pop()
                for x in blocks:
                    (b1, b2) = de_interleave(x)
                    (b1, b2, b3, b4) = slice(b1 + b2, 31)
                    self.descrambled += [b4, b2, b3, b1]
                (b1, b2) = de_interleave(end)
                self.descrambled += [b2[1:],
                                     b1[1:]]  # Throw away the extra bit
            else:  # Need to check what other ft are
                self.msgtype = "UK"
                self.descrambled = slice(data, 64)
                self.descramble_extra = ""

        self.lead_out_ok = self.descramble_extra.startswith(iridium_lead_out)
        if self.msgtype != "VO" and self.msgtype != "IP" and len(
                self.descrambled) == 0:
            self._new_error("No data to descramble")
示例#6
0
    def __init__(self,msg):
        self.__dict__=copy.deepcopy(msg.__dict__)
        data=self.bitstream_raw[len(iridium_access):]

        # Try to detect packet type
        if data[:32] == header_messaging:
            self.msgtype="MS"
        elif  1626229167<self.frequency<1626312500:
            self.msgtype="RA"
        elif len(data)>64: # XXX: heuristic based on LCW / first BCH block, can we do better?
            (lcw1,lcw2,lcw3)=de_interleave_lcw(data[:46])
            (e1,lcw1,bch)= bch_repair( 29,lcw1)
            (e2,lcw2,bch)= bch_repair(465,lcw2+'0')  # One bit error expected
            (e3,lcw3,bch)= bch_repair( 41,lcw3)
#            if e1>=0 and e2>=0 and e3>=0: # Valid LCW
            if e1==0 and 0<=e2<=1 and e3==0: # GOOD LCW
                self.msgtype="DA"
            elif len(data)>6+64 and ndivide(ringalert_bch_poly,de_interleave(data[6:6+64])[0][:31])==0:
                self.msgtype="BC"
            else:
                raise ParserError("unknown Iridium message type")
        else:
            raise ParserError("Iridium message too short")

        if self.msgtype=="MS":
            hdrlen=32
            self.header=data[:hdrlen]
            self.descrambled=[]
            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="RA":
            firstlen=3*32
            if len(data)<firstlen:
                self._new_error("No data to descramble")
            self.header=""
            self.descrambled=de_interleave3(data[:firstlen])
            (blocks,self.descramble_extra)=slice_extra(data[firstlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="BC":
            hdrlen=6
            self.header=data[:hdrlen]
            self.descrambled=[]

            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="DA":
            lcwlen=46
            (o_lcw1,o_lcw2,o_lcw3)=de_interleave_lcw(data[:lcwlen])
            (e1,self.lcw1,bch)= bch_repair( 29,o_lcw1)
            (e2,self.lcw2,bch)= bch_repair(465,o_lcw2+'0')  # One bit error expected
            (e3,self.lcw3,bch)= bch_repair( 41,o_lcw3)
            self.ft=int(self.lcw1,2) # Frame type
            if e1<0 or e2<0 or e3<0:
                self._new_error("LCW decode failed")
                self.header="LCW(%s %s/%02d E%d,%s %sx/%03d E%d,%s %s/%02d E%d)"%(o_ft[:3],o_ft[3:],ndivide(29,o_ft),e1,o_lcw2[:6],o_lcw2[6:],ndivide(465,o_lcw2+'0'),e2,o_lcw3[:21],o_lcw3[21:],ndivide(41,o_lcw3),e3)
            else:
                self.header="LCW(%d,%s,%s E%d)"%(self.ft,self.lcw2,self.lcw3,e1+e2+e3)
            self.descrambled=[]
            data=data[lcwlen:]

            if self.ft==0: # Voice
                self.msgtype="VO"
                self.voice=data[:312]
                self.descramble_extra=data[312:]
            elif self.ft==2:
                if len(data)<124*2+64:
                    self._new_error("Not enough data in DA packet")
                self.descramble_extra=data[124*2+64:]
                data=data[:124*2+64]
                blocks=slice(data,124)
                end=blocks.pop()
                for x in blocks:
                    for i in de_interleave(x): # Not clear what block order is correct
                        self.descrambled+=[i[:31],i[31:62]]
                self.descrambled+=de_interleave(end)
            else: # Need to check what ft=1 is
                self.descrambled=blocks=slice(data,64)
                self.descramble_extra=""
                self._new_error("Unknown frame_type")

        self.lead_out_ok= self.descramble_extra.startswith(iridium_lead_out)
        if self.msgtype!="VO" and len(self.descrambled)==0:
            self._new_error("No data to descramble")
示例#7
0
    def __init__(self, msg):
        self.__dict__ = copy.deepcopy(msg.__dict__)
        data = self.bitstream_raw[len(iridium_access):]

        # Try to detect packet type
        if data[:32] == header_messaging:
            self.msgtype = "MS"
        elif 1626229167 < self.frequency < 1626312500:
            self.msgtype = "RA"
        elif len(
                data
        ) > 64:  # XXX: heuristic based on LCW / first BCH block, can we do better?
            (lcw1, lcw2, lcw3) = de_interleave_lcw(data[:46])
            (e1, lcw1, bch) = bch_repair(29, lcw1)
            (e2, lcw2, bch) = bch_repair(465,
                                         lcw2 + '0')  # One bit error expected
            (e3, lcw3, bch) = bch_repair(41, lcw3)
            #            if e1>=0 and e2>=0 and e3>=0: # Valid LCW
            if e1 == 0 and 0 <= e2 <= 1 and e3 == 0:  # GOOD LCW
                self.msgtype = "DA"
            elif len(data) > 6 + 64 and ndivide(
                    ringalert_bch_poly,
                    de_interleave(data[6:6 + 64])[0][:31]) == 0:
                self.msgtype = "BC"
            else:
                raise ParserError("unknown Iridium message type")
        else:
            raise ParserError("Iridium message too short")

        if self.msgtype == "MS":
            hdrlen = 32
            self.header = data[:hdrlen]
            self.descrambled = []
            (blocks, self.descramble_extra) = slice_extra(data[hdrlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "RA":
            firstlen = 3 * 32
            if len(data) < firstlen:
                self._new_error("No data to descramble")
            self.header = ""
            self.descrambled = de_interleave3(data[:firstlen])
            (blocks, self.descramble_extra) = slice_extra(data[firstlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "BC":
            hdrlen = 6
            self.header = data[:hdrlen]
            self.descrambled = []

            (blocks, self.descramble_extra) = slice_extra(data[hdrlen:], 64)
            for x in blocks:
                self.descrambled += de_interleave(x)
        elif self.msgtype == "DA":
            lcwlen = 46
            (o_lcw1, o_lcw2, o_lcw3) = de_interleave_lcw(data[:lcwlen])
            (e1, self.lcw1, bch) = bch_repair(29, o_lcw1)
            (e2, self.lcw2,
             bch) = bch_repair(465, o_lcw2 + '0')  # One bit error expected
            (e3, self.lcw3, bch) = bch_repair(41, o_lcw3)
            self.ft = int(self.lcw1, 2)  # Frame type
            if e1 < 0 or e2 < 0 or e3 < 0:
                self._new_error("LCW decode failed")
                self.header = "LCW(%s %s/%02d E%d,%s %sx/%03d E%d,%s %s/%02d E%d)" % (
                    o_ft[:3], o_ft[3:], ndivide(29, o_ft), e1, o_lcw2[:6],
                    o_lcw2[6:], ndivide(465, o_lcw2 + '0'), e2, o_lcw3[:21],
                    o_lcw3[21:], ndivide(41, o_lcw3), e3)
            else:
                self.header = "LCW(%d,%s,%s E%d)" % (self.ft, self.lcw2,
                                                     self.lcw3, e1 + e2 + e3)
            self.descrambled = []
            data = data[lcwlen:]

            if self.ft == 0:  # Voice
                self.msgtype = "VO"
                self.voice = data[:312]
                self.descramble_extra = data[312:]
            elif self.ft == 2:
                if len(data) < 124 * 2 + 64:
                    self._new_error("Not enough data in DA packet")
                self.descramble_extra = data[124 * 2 + 64:]
                data = data[:124 * 2 + 64]
                blocks = slice(data, 124)
                end = blocks.pop()
                for x in blocks:
                    for i in de_interleave(
                            x):  # Not clear what block order is correct
                        self.descrambled += [i[:31], i[31:62]]
                self.descrambled += de_interleave(end)
            else:  # Need to check what ft=1 is
                self.descrambled = blocks = slice(data, 64)
                self.descramble_extra = ""
                self._new_error("Unknown frame_type")

        self.lead_out_ok = self.descramble_extra.startswith(iridium_lead_out)
        if self.msgtype != "VO" and len(self.descrambled) == 0:
            self._new_error("No data to descramble")
    def __init__(self,msg):
        self.__dict__=msg.__dict__
        if (self.uplink):
            data=self.bitstream_raw[len(uplink_access):]
        else:
            data=self.bitstream_raw[len(iridium_access):]

        # Try to detect packet type.
        # XXX: will not detect packets with correctable bit errors at the beginning
        if "msgtype" not in self.__dict__:
            if data[:32] == header_messaging:
                self.msgtype="MS"

        if "msgtype" not in self.__dict__:
            hdrlen=6
            blocklen=64
            if len(data)>hdrlen+blocklen:
                (o_bc1,o_bc2)=de_interleave(data[hdrlen:hdrlen+blocklen])
                if ndivide(ringalert_bch_poly,o_bc1[:31])==0:
                    if ndivide(ringalert_bch_poly,o_bc2[:31])==0:
                        self.msgtype="BC"

        if "msgtype" not in self.__dict__:
            if len(data)>64: # XXX: heuristic based on LCW / first BCH block, can we do better?
                (o_lcw1,o_lcw2,o_lcw3)=de_interleave_lcw(data[:46])
                if ndivide( 29,o_lcw1)==0:
                    if ndivide( 41,o_lcw3)==0:
                        (e2,lcw2,bch)= bch_repair(465,o_lcw2+'0')  # One bit missing, so we guess
                        if (e2==1): # Maybe the other one...
                            (e2,lcw2,bch)= bch_repair(465,o_lcw2+'1')
                        if e2==0:
                            self.msgtype="DA"

        if "msgtype" not in self.__dict__:
            firstlen=3*32
            if len(data)>=3*32:
                (o_ra1,o_ra2,o_ra3)=de_interleave3(data[:firstlen])
                if ndivide(ringalert_bch_poly,o_ra1[:31])==0:
                    if ndivide(ringalert_bch_poly,o_ra2[:31])==0:
                        if ndivide(ringalert_bch_poly,o_ra3[:31])==0:
                            self.msgtype="RA"

        if "msgtype" not in self.__dict__:
            if len(data)<64:
                raise ParserError("Iridium message too short")
            else:
                raise ParserError("unknown Iridium message type")

        if self.msgtype=="MS":
            hdrlen=32
            self.header=data[:hdrlen]
            self.descrambled=[]
            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="RA":
            firstlen=3*32
            if len(data)<firstlen:
                self._new_error("No data to descramble")
            self.header=""
            self.descrambled=de_interleave3(data[:firstlen])
            (blocks,self.descramble_extra)=slice_extra(data[firstlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="BC":
            hdrlen=6
            self.header=data[:hdrlen]
            self.descrambled=[]

            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="DA":
            lcwlen=46
            (o_lcw1,o_lcw2,o_lcw3)=de_interleave_lcw(data[:lcwlen])
            (e1,self.lcw1,bch)= bch_repair( 29,o_lcw1)
            (e2,self.lcw2,bch)= bch_repair(465,o_lcw2+'0')  # One bit error expected
            if e2==1:
                (e2,self.lcw2,bch)= bch_repair(465,o_lcw2+'1')  # Other bit flip?
            (e3,self.lcw3,bch)= bch_repair( 41,o_lcw3)
            self.ft=int(self.lcw1,2) # Frame type
            if e1<0 or e2<0 or e3<0:
# LCW:=xx[type] yyyy[code]
# 0: maint
#    6: geoloc
#    f: "no text"
#    c: maint [lqi[x1c,2], power[[x19,3]]
#    789abde: reserved
#    0: sync [status[xa,1], dtoa[xc,10], dfoa[x16,8]]
#    3: maint [lqi[xa,2], power[xc,3], fine dtoa[xf,7], fine dfoa[x16,3]]
#    245: reserved
#    1: switch [dtoa[xc,10], dfoa[x16,8]]
# 1: acchl
#    1: acchl
#    *: reserved
# 2: handoff
#    c: handoff cand.
#    f: "no text"
#    3: handoff resp. [cand[%c[0=P,1=S::0xb,1]], denied[0xc,1], ref[xd,1], slot[xf,2]+1, subband up[x11,5], subband down[x16,5], access[x1b,3]+1]
#    *: reserved
# 3: reserved
                self._new_error("LCW decode failed")
                self.header="LCW(%s %s/%02d E%d,%s %sx/%03d E%d,%s %s/%02d E%d)"%(o_ft[:3],o_ft[3:],ndivide(29,o_ft),e1,o_lcw2[:6],o_lcw2[6:],ndivide(465,o_lcw2+'0'),e2,o_lcw3[:21],o_lcw3[21:],ndivide(41,o_lcw3),e3)
            else:
#                self.header="LCW(%d,%s,%s E%d)"%(self.ft,self.lcw2,self.lcw3,e1+e2+e3)
                self.lcw_ft=int(self.lcw2[:2],2)
                self.lcw_code=int(self.lcw2[2:],2)
                if self.lcw_ft == 0:
                    ty="maint"
                    if self.lcw_code == 6:
                        code="geoloc"
                    elif self.lcw_code == 15:
                        code="<silent>"
                    elif self.lcw_code == 12:
                        code="maint[1]"
                        code+="[lqi:%d,power:%d]"%(int(self.lcw3[19:21],2),int(self.lcw3[16:19],2))
                    elif self.lcw_code == 0:
                        code="sync"
                        code+="[status:%d,dtoa:%d,dfoa:%d]"%(int(self.lcw3[1:2],2),int(self.lcw3[3:13],2),int(self.lcw3[13:21],2))
                    elif self.lcw_code == 3:
                        code="maint[2]"
                        code+="[lqi:%d,power:%d,f_dtoa:%d,f_dfoa:%d]"%(int(self.lcw3[1:3],2),int(self.lcw3[3:6],2),int(self.lcw3[6:13],2),int(self.lcw3[13:20],2))
                    elif self.lcw_code == 1:
                        code="switch"
                        code+="[dtoa:%d,dfoa:%d]"%(int(self.lcw3[3:13],2),int(self.lcw3[13:21],2))
                    else:
                        code="rsrvd"
                elif self.lcw_ft == 1:
                    ty="acchl"
                    if self.lcw_code == 1:
                        code="acchl"
                    else:
                        code="rsrvd"
                elif self.lcw_ft == 2:
                    ty="hndof"
                    if self.lcw_code == 12:
                        code="handoff_cand"
                    elif self.lcw_code == 3:
                        code="handoff_resp"
                        code+="[cand:%d,denied:%d,ref:%d,slot:%d,sband_up:%d,sband_dn:%d,access:%d]"%(int(self.lcw3[2:3],2),int(self.lcw3[3:4],2),int(self.lcw3[4:5],2),1+int(self.lcw3[6:8],2),int(self.lcw3[8:13],2),int(self.lcw3[13:18],2),1+int(self.lcw3[18:21],2))
                    elif self.lcw_code == 15:
                        code="<silent>"
                    else:
                        code="rsrvd"
                elif self.lcw_ft == 3:
                    ty="rsrvd"
                    code="<>"
                self.header="LCW(%d,T:%s,C:%s(%s),%s E%d)"%(self.ft,ty,code,int(self.lcw2,2),int(self.lcw3,2),e1+e2+e3)
                self.header="%-110s "%self.header
            self.descrambled=[]
            data=data[lcwlen:]

            def symbol_reverse(bits):
                r = ''
                for symbol in grouped(bits, 2):
                    r += symbol[1] + symbol[0]
                return r
            if self.ft<=2 and len(data)<312:
                    self._new_error("Not enough data in data packet")
            if self.ft==0: # Voice
                self.msgtype="VO"
                self.voice=data[:312]
                self.descramble_extra=data[312:]
            elif self.ft==1: # IP via PPP
                self.msgtype="IP"
                for x in slice(symbol_reverse(data[:312]),8):
                    self.descrambled+=[x[::-1]]
                self.descramble_extra=data[312:]
            elif self.ft==2: # DAta (SBD)
                self.descramble_extra=data[124*2+64:]
                data=data[:124*2+64]
                blocks=slice(data,124)
                end=blocks.pop()
                for x in blocks:
                    (b1,b2)=de_interleave(x)
                    (b1,b2,b3,b4)=slice(b1+b2,31)
                    self.descrambled+=[b4,b2,b3,b1]
                (b1,b2)=de_interleave(end)
                self.descrambled+=[b2[1:],b1[1:]] # Throw away the extra bit
            elif self.ft==7: # Synchronisation
                self.msgtype="SY"
                self.descrambled=data[:312]
                self.sync=[int(x,2) for x in slice(self.descrambled, 8)]
                self.descramble_extra=data[312:]
            else: # Need to check what other ft are
                self.msgtype="UK"
                self.descrambled=symbol_reverse(data[:312])
                self.descramble_extra=data[312:]

        self.lead_out_ok= self.descramble_extra.startswith(iridium_lead_out)
        if self.msgtype!="VO" and self.msgtype!="IP" and len(self.descrambled)==0:
            self._new_error("No data to descramble")
    def __init__(self,msg):
        self.__dict__=copy.deepcopy(msg.__dict__)
        data=self.bitstream_raw[len(iridium_access):]

        # Try to detect packet type
        if data[:32] == header_messaging:
            self.msgtype="MS"
        elif  1626229167<self.frequency<1626312500:
            self.msgtype="RA"
        elif len(data)>64: # XXX: heuristic based on LCW / first BCH block, can we do better?
            (o_lcw1,o_lcw2,o_lcw3)=de_interleave_lcw(data[:46])
            (e1,lcw1,bch)= bch_repair( 29,o_lcw1)
            (e2,lcw2,bch)= bch_repair(465,o_lcw2+'0')  # One bit missing, so we guess
            if (e2==1): # Maybe the other one...
                (e2,lcw2,bch)= bch_repair(465,o_lcw2+'1')
            (e3,lcw3,bch)= bch_repair( 41,o_lcw3)
#            if e1>=0 and e2>=0 and e3>=0: # Valid LCW
            if e1==0 and e2==0 and e3==0: # GOOD LCW
                self.msgtype="DA"
            elif len(data)>6+64 and ndivide(ringalert_bch_poly,de_interleave(data[6:6+64])[0][:31])==0:
                self.msgtype="BC"
            else:
                raise ParserError("unknown Iridium message type")
        else:
            raise ParserError("Iridium message too short")

        if self.msgtype=="MS":
            hdrlen=32
            self.header=data[:hdrlen]
            self.descrambled=[]
            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="RA":
            firstlen=3*32
            if len(data)<firstlen:
                self._new_error("No data to descramble")
            self.header=""
            self.descrambled=de_interleave3(data[:firstlen])
            (blocks,self.descramble_extra)=slice_extra(data[firstlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="BC":
            hdrlen=6
            self.header=data[:hdrlen]
            self.descrambled=[]

            (blocks,self.descramble_extra)=slice_extra(data[hdrlen:],64)
            for x in blocks:
                self.descrambled+=de_interleave(x)
        elif self.msgtype=="DA":
            lcwlen=46
            (o_lcw1,o_lcw2,o_lcw3)=de_interleave_lcw(data[:lcwlen])
            (e1,self.lcw1,bch)= bch_repair( 29,o_lcw1)
            (e2,self.lcw2,bch)= bch_repair(465,o_lcw2+'0')  # One bit error expected
            if e2==1:
                (e2,self.lcw2,bch)= bch_repair(465,o_lcw2+'1')  # Other bit flip?
            (e3,self.lcw3,bch)= bch_repair( 41,o_lcw3)
            self.ft=int(self.lcw1,2) # Frame type
            if e1<0 or e2<0 or e3<0:
                self._new_error("LCW decode failed")
                self.header="LCW(%s %s/%02d E%d,%s %sx/%03d E%d,%s %s/%02d E%d)"%(o_ft[:3],o_ft[3:],ndivide(29,o_ft),e1,o_lcw2[:6],o_lcw2[6:],ndivide(465,o_lcw2+'0'),e2,o_lcw3[:21],o_lcw3[21:],ndivide(41,o_lcw3),e3)
            else:
                self.header="LCW(%d,%s,%s E%d)"%(self.ft,self.lcw2,self.lcw3,e1+e2+e3)
            self.descrambled=[]
            data=data[lcwlen:]

            def symbol_reverse(bits):
                r = ''
                for symbol in grouped(bits, 2):
                    r += symbol[1] + symbol[0]
                return r
            if self.ft<=2 and len(data)<312:
                    self._new_error("Not enough data in data packet")
            if self.ft==0: # Voice
                self.msgtype="VO"
                self.voice=data[:312]
                self.descramble_extra=data[312:]
            elif self.ft==1: # IP via PPP
                self.msgtype="IP"
                for x in slice(symbol_reverse(data[:312]),8):
                    self.descrambled+=[x[::-1]]
                self.descramble_extra=data[312:]
            elif self.ft==2: # DAta (SBD)
                self.descramble_extra=data[124*2+64:]
                data=data[:124*2+64]
                blocks=slice(data,124)
                end=blocks.pop()
                for x in blocks:
                    (b1,b2)=de_interleave(x)
                    (b1,b2,b3,b4)=slice(b1+b2,31)
                    self.descrambled+=[b4,b2,b3,b1]
                (b1,b2)=de_interleave(end)
                self.descrambled+=[b2[1:],b1[1:]] # Throw away the extra bit
            else: # Need to check what other ft are
                self.msgtype="UK"
                self.descrambled=slice(data,64)
                self.descramble_extra=""

        self.lead_out_ok= self.descramble_extra.startswith(iridium_lead_out)
        if self.msgtype!="VO" and self.msgtype!="IP" and len(self.descrambled)==0:
            self._new_error("No data to descramble")