Ejemplo n.º 1
0
 def _tx_string(self, s):
     """This is only safe if it's guaranteed the card won't send any data
     during the time of tx of the string !!!"""
     self._sl.write(s)
     r = self._sl.read(len(s))
     if r != s:  # TX and RX are tied, so we must clear the echo
         raise ProtocolError("Bad echo value (Expected: %s, got %s)" %
                             (b2h(s), b2h(r)))
Ejemplo n.º 2
0
def getitem(path):
    if not os.path.exists(path) and not os.path.islink(path): return False
    name = os.path.basename(path)
    basepath = os.path.dirname(path)
    stat = os.lstat(path)
    mode = stat.st_mode
    try:
        uname = pwd.getpwuid(stat.st_uid).pw_name
    except:
        uname = ''
    try:
        gname = grp.getgrgid(stat.st_gid).gr_name
    except:
        gname = ''
    item = {
        'name': name,
        'isdir': S_ISDIR(mode),
        #'ischr': S_ISCHR(mode),
        #'isblk': S_ISBLK(mode),
        'isreg': S_ISREG(mode),
        #'isfifo': S_ISFIFO(mode),
        'islnk': S_ISLNK(mode),
        #'issock': S_ISSOCK(mode),
        'perms': oct(stat.st_mode & 0777),
        'uid': stat.st_uid,
        'gid': stat.st_gid,
        'uname': uname,
        'gname': gname,
        'size': b2h(stat.st_size),
        'atime': ftime(stat.st_atime),
        'mtime': ftime(stat.st_mtime),
        'ctime': ftime(stat.st_ctime),
    }
Ejemplo n.º 3
0
 def _parse(self, data, direction, cipher, decomp, buf):
     if cipher:
         data = rc4.crypt(data, cipher)
     if decomp:
         data = decomp.decompress(data)
     # Parse packet
     buf += data
     packets = []
     while buf:
         data = buf
         opcode, data = parse_cui(data)
         length, data = parse_cui(data)
         if len(data) < length and decomp:
             log.msg("Not enough data...")
             break
         else:
             data, buf = data[:length], data[length:]
             assert len(
                 data
             ) == length, "Real length - %s, expected - %s, data - %s" % (
                 len(data), length, utils.b2h(data))
             self.log_packet(direction, opcode, data)
             if opcode in PARSE_TABLE:
                 packet = PARSE_TABLE[opcode](data)
             else:
                 packet = dict(unknown=data)
             packet['opcode'] = opcode
             packets.append(packet)
     return packets, buf
Ejemplo n.º 4
0
 def unblock_chv(self, chv_no, code):
     self.select_file(['3f00', '7f20', '6f38'])
     fc = rpad(b2h(code.encode()), 16)
     if chv_no == 1:
         chv_no = 0
     return self._tp.send_apdu_checksw("a02c00" + ('%02x' % chv_no) + "10" +
                                       fc)
Ejemplo n.º 5
0
 def dataReceived(self, data):
     log.msg("Received data: %s" % utils.b2h(data))
     try:
         self.handler.handle(data, self.is_in)
     except:
         log.err()
         self.closeConnection()
         return
     self._out.transport.write(data)
Ejemplo n.º 6
0
 def dataReceived(self, data):
     log.msg("Received data: %s" % utils.b2h(data))
     try:
         self.handler.handle(data, self.is_in)
     except:
         log.err()
         self.closeConnection()
         return
     self._out.transport.write(data)
Ejemplo n.º 7
0
 def mounts(self, detectdev=False):
     mounts = []
     with open('/proc/mounts', 'r') as f:
         for line in f:
             dev, path, fstype = line.split()[0:3]
             if fstype in ('ext2', 'ext3', 'ext4', 'xfs', 'jfs', 'reiserfs',
                           'btrfs', 'simfs'):  # simfs: filesystem in OpenVZ
                 if not os.path.isdir(path): continue
                 mounts.append({'dev': dev, 'path': path, 'fstype': fstype})
     for mount in mounts:
         stat = os.statvfs(mount['path'])
         total = stat.f_blocks * stat.f_bsize
         free = stat.f_bfree * stat.f_bsize
         used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize
         mount['total'] = b2h(total)
         mount['free'] = b2h(free)
         mount['used'] = b2h(used)
         mount['used_rate'] = div_percent(used, total)
         if detectdev:
             dev = os.stat(mount['path']).st_dev
             mount['major'], mount['minor'] = os.major(dev), os.minor(dev)
     return mounts
Ejemplo n.º 8
0
 def log_packet(self, direction, opcode, data):
     if not ((self.log_opcodes and opcode not in self.log_opcodes) or
             (self.skip_opcodes and opcode in self.skip_opcodes)):
         # Packet will be logged:
         # if log_opcodes is not set
         # if log_opcodes is set and opcode present in log_opcodes
         # if skip_opcodes is not set
         # if skip_opcodes is set and opcode is not present into skip_opcodes
         l_time = time.ctime().split()[3]
         print >> self.out_stream, ' | '.join(
             (l_time, 'h', direction, '0x%X' % opcode, str(len(data)),
              utils.b2h(data)))
         print >> self.out_stream, ' | '.join(
             (l_time, 'a', direction, '0x%X' % opcode, str(len(data)),
              data))
Ejemplo n.º 9
0
def getitem(path):
    if not os.path.exists(path) and not os.path.islink(path): return False
    name = os.path.basename(path)
    basepath = os.path.dirname(path)
    stat = os.lstat(path)
    mode = stat.st_mode
    try:
        uname = pwd.getpwuid(stat.st_uid).pw_name
    except:
        uname = ''
    try:
        gname = grp.getgrgid(stat.st_gid).gr_name
    except:
        gname = ''
    item = {
        'name': name,
        'isdir': S_ISDIR(mode),
        #'ischr': S_ISCHR(mode),
        #'isblk': S_ISBLK(mode),
        'isreg': S_ISREG(mode),
        #'isfifo': S_ISFIFO(mode),
        'islnk': S_ISLNK(mode),
        #'issock': S_ISSOCK(mode),
        'perms': oct(stat.st_mode & 0777),
        'uid': stat.st_uid,
        'gid': stat.st_gid,
        'uname': uname,
        'gname': gname,
        'size': b2h(stat.st_size),
        'atime': ftime(stat.st_atime),
        'mtime': ftime(stat.st_mtime),
        'ctime': ftime(stat.st_ctime),
    }
    if item['islnk']:
        linkfile = os.readlink(path)
        item['linkto'] = linkfile
        if not linkfile.startswith('/'):
            linkfile = os.path.abspath(os.path.join(basepath, linkfile))
        try:
            stat = os.stat(linkfile)
            item['link_isdir'] = S_ISDIR(stat.st_mode)
            item['link_isreg'] = S_ISREG(stat.st_mode)
            item['link_broken'] = False
        except:
            item['link_broken'] = True
    return item
Ejemplo n.º 10
0
    def program(self, p):
        # Go to dir
        self._scc.select_file(['3f00', '7f4d'])

        # Home PLMN in PLMN_Sel format
        hplmn = self._e_plmn(p['mcc'], p['mnc'])

        # Operator name ( 3f00/7f4d/8f0c )
        self._scc.update_record(
            self._files['name'][0], 2,
            rpad(b2h(p['name']), 32) + ('%02x' % len(p['name'])) + '01')

        # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
        v = ''

        # inline Ki
        if self._ki_file is None:
            v += p['ki']

            # ICCID
        v += '3f00' + '2fe2' + '0a' + self._e_iccid(p['iccid'])

        # IMSI
        v += '7f20' + '6f07' + '09' + self._e_imsi(p['imsi'])

        # Ki
        if self._ki_file:
            v += self._ki_file + '10' + p['ki']

            # PLMN_Sel
        v += '6f30' + '18' + rpad(hplmn, 36)

        self._scc.update_record(self._files['b_ef'][0], 1,
                                rpad(v, self._files['b_ef'][1] * 2))

        # SMSP ( 3f00/7f4d/8f0e )
        # FIXME

        # Write PLMN_Sel forcefully as well
        r = self._scc.select_file(['3f00', '7f20', '6f30'])
        tl = int(r[-1][4:8], 16)

        hplmn = self._e_plmn(p['mcc'], p['mnc'])
        self._scc.update_binary('6f30', hplmn + 'ff' * (tl - 3))
Ejemplo n.º 11
0
    def meminfo(self):
        # OpenVZ may not have some varirables
        # so init them first
        mem_total = mem_free = mem_buffers = mem_cached = swap_total = swap_free = 0

        with open('/proc/meminfo', 'r') as f:
            for line in f:
                if ':' not in line:
                    continue
                item, value = line.split(':')
                value = int(value.split()[0]) * 1024
                if item == 'MemTotal':
                    mem_total = value
                elif item == 'MemFree':
                    mem_free = value
                elif item == 'Buffers':
                    mem_buffers = value
                elif item == 'Cached':
                    mem_cached = value
                elif item == 'SwapTotal':
                    swap_total = value
                elif item == 'SwapFree':
                    swap_free = value

        mem_used = mem_total - mem_free
        swap_used = swap_total - swap_free
        return {
            'mem_total': b2h(mem_total),
            'mem_used': b2h(mem_used),
            'mem_free': b2h(mem_free),
            'mem_buffers': b2h(mem_buffers),
            'mem_cached': b2h(mem_cached),
            'swap_total': b2h(swap_total),
            'swap_used': b2h(swap_used),
            'swap_free': b2h(swap_free),
            'mem_used_rate': div_percent(mem_used, mem_total),
            'mem_free_rate': div_percent(mem_free, mem_total),
            'swap_used_rate': div_percent(swap_used, swap_total),
            'swap_free_rate': div_percent(swap_free, swap_total),
        }
Ejemplo n.º 12
0
    def program(self, p):
        # Home PLMN
        r = self._scc.select_file(['3f00', '7f20', '6f30'])
        tl = int(r[-1][4:8], 16)

        hplmn = self._e_plmn(p['mcc'], p['mnc'])
        self._scc.update_binary('6f30', hplmn + 'ff' * (tl - 3))

        # Get total number of entries and entry size
        rec_cnt, rec_len = self._get_infos()

        # Set first entry
        entry = (
            '81' +  #  1b  Status: Valid & Active
            rpad(b2h(p['name'][0:14]), 28) +  # 14b  Entry Name
            self._e_iccid(p['iccid']) +  # 10b  ICCID
            self._e_imsi(p['imsi']) +  #  9b  IMSI_len + id_type(9) + IMSI
            p['ki'] +  # 16b  Ki
            lpad(p['smsp'], 80)  # 40b  SMSP (padded with ff if needed)
        )
        self._scc.update_record('000c', 1, entry)
Ejemplo n.º 13
0
    decomp.in_buf = p
    for exp in (7, 0, 5, 2, 0):
        real = decomp._get_bits(3)
        assert real == exp, "%s != %s" % (real, exp)
        #print "%s - OK" % exp
    #print decomp._get_bits(1)
    #print decomp._get_bits(1)

if __name__ == "__main__":
    import cProfile
    import utils
    s = '04 1C 00 95 0D C8 00 01 5B 6F 00 1E 08 2F C4 00 5F FC 17 91 1E 23 C0'
    #s = 'E2 A0'
    p = ''.join(chr(int(i, 16)) for i in s.split())

    #cProfile.run('for i in xrange(10000): test_bitstring(p)')
    #cProfile.run('for i in xrange(10000): test_get_bits(p)')

    decomp_gb = MPPCDecoder()
    d = decomp_gb.decompress(p)
    print utils.b2h(d)
    print len(d) == int('1c', 16) + 2
    decomp_gen = mppc()
    d = decomp_gen.send(p)
    print utils.b2h(d)
    print len(d) == int('1c', 16) + 2

    cProfile.run('for i in xrange(10000): decomp_gen.send(p)')
    cProfile.run('for i in xrange(10000): decomp_gb.decompress(p)')

Ejemplo n.º 14
0
    def diskinfo(self):
        """Return a dictionary contain info of all disks and partitions.
        """
        disks = {
            'count': 0,
            'totalsize': 0,
            'partitions': [],
            'lvm': {
                'partcount': 0,
                'unpartition': 0,
                'partitions': []
            }
        }
        
        # read mount points
        mounts = Server.mounts(True)
        
        # scan for uuid and filesystem of partitions
        blks = Server.partinfo()

        # OpenVZ may not have blk info
        if not blks: return disks

        for devname, blkinfo in blks.iteritems():
            dev = os.stat('/dev/%s' % devname).st_rdev
            major, minor = os.major(dev), os.minor(dev)
            blks[devname]['major'] = major
            blks[devname]['minor'] = minor

        parts = []
        with open('/proc/partitions', 'r') as f:
            for line in f:
                fields = line.split()
                if len(fields) == 0: continue
                if not fields[0].isdigit(): continue
                major, minor, blocks, name = fields
                major, minor, blocks = int(major), int(minor), int(blocks)
                parts.append({
                    'name': name,
                    'major': major,
                    'minor': minor,
                    'blocks': blocks,
                })

        # check if some unmounted partition is busy
        has_busy_part = False
        for i, part in enumerate(parts):
            # check if it appears in blkid list
            if not blks.has_key(part['name']):
                # don't check the part with child partition
                if i+1<len(parts) and parts[i+1]['name'].startswith(part['name']):
                    continue
                
                # if dev name doesn't match, check the major and minor of the dev
                devfound = False
                for devname, blkinfo in blks.iteritems():
                    if blkinfo['major'] == part['major'] and blkinfo['minor'] == part['minor']:
                        devfound = True
                        break
                if devfound: continue

                # means that it is busy
                has_busy_part = True
                break

        # scan for lvm logical volume
        lvmlvs = []
        lvmlvs_vname = {}
        if not has_busy_part and os.path.exists('/sbin/lvm'):
            p = subprocess.Popen(shlex.split('/sbin/lvm lvdisplay'), stdout=subprocess.PIPE, close_fds=True)
            lvs = p.stdout
            while True:
                line = lvs.readline()
                if not line: break
                if 'LV Name' in line or 'LV Path' in line:
                    devlink = line.replace('LV Name', '').replace('LV Path', '').strip()
                    if not os.path.exists(devlink): continue
                    dev = os.readlink(devlink)
                    dev = os.path.abspath(os.path.join(os.path.dirname(devlink), dev))
                    dev = dev.replace('/dev/', '')
                    lvmlvs_vname[dev] = devlink.replace('/dev/', '')
                    lvmlvs.append(dev)
            p.wait()
        
        # scan for the 'on' status swap partition
        swapptns = []
        with open('/proc/swaps', 'r') as f:
            for line in f:
                if not line.startswith('/dev/'): continue
                fields = line.split()
                swapptns.append(fields[0].replace('/dev/', ''))

        for part in parts:
            name = part['name']
            major = part['major']
            minor = part['minor']
            blocks = part['blocks']

            # check if the partition is a hardware disk
            # we treat name with no digit as a hardware disk
            is_hw = True
            partcount = 0
            unpartition = 0
            if len([x for x in name if x.isdigit()]) > 0 or name in lvmlvs:
                is_hw = False

            # determine which disk this partition belong to
            # and calcular the unpartition disk space
            parent_part = disks
            parent_part_found = False
            for i, ptn in enumerate(disks['partitions']):
                if name.startswith(ptn['name']):
                    parent_part_found = True
                    parent_part = disks['partitions'][i]
                    parent_part['partcount'] += 1
                    parent_part['unpartition'] -= blocks*1024
                    break
            if not is_hw and not parent_part_found:
                parent_part = disks['lvm']

            if blks.has_key(name) and blks[name]['fstype'].startswith('LVM'):
                is_pv = True
            else:
                is_pv = False
            
            partition = {
                'major': major,
                'minor': minor,
                'name': name,
                'size': b2h(blocks*1024),
                'is_hw': is_hw,
                'is_pv': is_pv,
                'partcount': partcount,
            }

            if blks.has_key(name):
                partition['fstype'] = blks[name]['fstype']
                partition['uuid'] = blks[name]['uuid']
            
            if name in lvmlvs:
                partition['is_lv'] = True
                partition['vname'] = lvmlvs_vname[name]
            else:
                partition['is_lv'] = False

            for mount in mounts:
                if mount['major'] == major and mount['minor'] == minor:
                    partition['mount'] = mount['path']
                    # read filesystem type from blkid
                    #partition['fstype'] = mount['fstype']
                    break
            if name in swapptns:
                partition['fstype'] = 'swap'
                partition['mount'] = 'swap'

            if is_hw:
                partition['partitions'] = []
                partition['unpartition'] = blocks*1024
                disks['count'] += 1
                disks['totalsize'] += blocks*1024

            parent_part['partitions'].append(partition)

        disks['totalsize'] = b2h(disks['totalsize'])
        disks['lvscount'] = len(lvmlvs)
        for i, part in enumerate(disks['partitions']):
            unpartition = part['unpartition']
            if unpartition <= 10*1024**2:   # ignore size < 10MB
                unpartition = '0'
            else:
                unpartition = b2h(unpartition)
            disks['partitions'][i]['unpartition'] = unpartition
        return disks
Ejemplo n.º 15
0
 def verify_chv(self, chv_no, code):
     self.select_file(['3f00', '7f20'])
     fc = rpad(b2h(code.encode()), 16)
     return self._tp.send_apdu_checksw('a02000' + ('%02x' % chv_no) + '08' +
                                       fc)
Ejemplo n.º 16
0
 def disable_chv(self, code):
     fc = rpad(b2h(code.encode()), 16)
     return self._tp.send_apdu_checksw('a026000108' + fc)
Ejemplo n.º 17
0
    def netifaces(self):
        netifaces = []
        with open('/proc/net/dev', 'r') as f:
            for line in f:
                if not ':' in line: continue
                name, data = line.split(':')
                name = name.strip()
                data = data.split()
                rx = int(data[0])
                tx = int(data[8])
                netifaces.append({
                    'name': name,
                    'rx': b2h(rx),
                    'tx': b2h(tx),
                    'timestamp': int(time.time()),
                    'rx_bytes': rx,
                    'tx_bytes': tx,
                })
        with open('/proc/net/route') as f:
            for line in f:
                fields = line.strip().split()
                if fields[1] != '00000000' or not int(fields[3], 16) & 2:
                    continue
                gw = socket.inet_ntoa(struct.pack('<L', int(fields[2], 16)))
                for netiface in netifaces:
                    if netiface['name'] == fields[0]:
                        netiface['gw'] = gw
                        break
        # REF: http://linux.about.com/library/cmd/blcmdl7_netdevice.htm
        for i, netiface in enumerate(netifaces):
            guess_iface = False
            while True:
                try:
                    ifname = netiface['name'][:15]
                    ifnamepack = struct.pack('256s', ifname)
                    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                    sfd = s.fileno()
                    flags, = struct.unpack('H', fcntl.ioctl(
                        sfd, 0x8913,  # SIOCGIFFLAGS
                        ifnamepack
                    )[16:18])
                    netiface['status'] = ('down', 'up')[flags & 0x1]
                    netiface['ip'] = socket.inet_ntoa(fcntl.ioctl(
                        sfd, 0x8915,  # SIOCGIFADDR
                        ifnamepack
                    )[20:24])
                    netiface['bcast'] = socket.inet_ntoa(fcntl.ioctl(
                        sfd, 0x8919,  # SIOCGIFBRDADDR
                        ifnamepack
                    )[20:24])
                    netiface['mask'] = socket.inet_ntoa(fcntl.ioctl(
                        sfd, 0x891b,  # SIOCGIFNETMASK
                        ifnamepack
                    )[20:24])
                    hwinfo = fcntl.ioctl(
                        sfd, 0x8927,  # SIOCSIFHWADDR
                        ifnamepack)
                    # REF: networking/interface.c, /usr/include/linux/if.h, /usr/include/linux/if_arp.h
                    encaps = {
                        '\xff\xff': 'UNSPEC',                   # -1
                        '\x01\x00': 'Ethernet',                 # 1
                        '\x00\x02': 'Point-to-Point Protocol',  # 512
                        '\x04\x03': 'Local Loopback',           # 772
                        '\x08\x03': 'IPv6-in-IPv4',             # 776
                        '\x20\x00': 'InfiniBand',               # 32
                    }
                    hwtype = hwinfo[16:18]
                    netiface['encap'] = encaps[hwtype]
                    netiface['mac'] = ':'.join(['%02X' % ord(char) for char in hwinfo[18:24]])
    
                    if not netiface['name'].startswith('venet'): break

                    # detect interface like venet0:0, venet0:1, etc.
                    if not guess_iface:
                        guess_iface = True
                        guess_iface_name = netiface['name']
                        guess_iface_i = 0
                    else:
                        netifaces.append(netiface)
                        guest_iface_i += 1

                    netiface = {
                        'name': '%s:%d' % (guess_iface_name, guess_iface_i),
                        'rx': '0B',
                        'tx': '0B',
                        'timestamp': 0,
                        'rx_bytes': 0,
                        'tx_bytes': 0,
                    }
                except:
                    #netifaces[i] = None
                    break
                
        netifaces = [ iface for iface in netifaces if iface.has_key('mac') ]
        return netifaces
Ejemplo n.º 18
0
 def enable_chv(self, code):
     self.select_file(['3f00', '7f20', '6f38'])
     fc = rpad(b2h(code.encode()), 16)
     return self._tp.send_apdu_checksw("a028000108" + fc)
Ejemplo n.º 19
0
 def log_packet(self, direction, opcode, data):
     if not ((self.log_opcodes and opcode not in self.log_opcodes) or (self.skip_opcodes and opcode in self.skip_opcodes)):
         # Packet will be logged:
         # if log_opcodes is not set
         # if log_opcodes is set and opcode present in log_opcodes
         # if skip_opcodes is not set
         # if skip_opcodes is set and opcode is not present into skip_opcodes
         l_time = time.ctime().split()[3]
         print >> self.out_stream, ' | '.join((l_time, 'h', direction, '0x%X' % opcode, str(len(data)), utils.b2h(data)))
         print >> self.out_stream, ' | '.join((l_time, 'a', direction, '0x%X' % opcode, str(len(data)), data))
Ejemplo n.º 20
0
 def _parse(self, data, direction, cipher, decomp, buf):
     if cipher:
         data = rc4.crypt(data, cipher)
     if decomp:
         data = decomp.decompress(data)
     # Parse packet
     buf += data
     packets = []
     while buf:
         data = buf
         opcode, data = parse_cui(data)
         length, data = parse_cui(data)
         if len(data) < length and decomp:
             log.msg("Not enough data...")
             break
         else:
             data, buf = data[:length], data[length:]
             assert len(data) == length, "Real length - %s, expected - %s, data - %s" % (len(data), length, utils.b2h(data))
             self.log_packet(direction, opcode, data)
             if opcode in PARSE_TABLE:
                 packet = PARSE_TABLE[opcode](data)
             else:
                 packet = dict(unknown=data)
             packet['opcode'] = opcode
             packets.append(packet)
     return packets, buf
Ejemplo n.º 21
0
 def change_chv(self, chv_no, curr_pin, new_pin):
     fc = rpad(b2h(curr_pin.encode()), 16) + rpad(b2h(new_pin.encode()), 16)
     return self._tp.send_apdu_checksw("a02400" + ('%02x' % chv_no) + "10" +
                                       fc)
Ejemplo n.º 22
0
    def send_apdu_raw(self, pdu):
        """see LinkBase.send_apdu_raw"""

        self._dbg_print("Command:" + pdu)
        pdu1 = h2b(pdu)
        data_len = int(pdu[8:11], 16)  # P3

        # Send first CLASS,INS,P1,P2,P3
        pdu2 = pdu1[0:5]
        self._tx_string(pdu1[0:5])

        # Wait ack which can be
        #  - INS: Command acked -> go ahead
        #  - 0x60: NULL, just wait some more
        #  - SW1: The card can apparently proceed ...
        while True:
            b = self._rx_byte()
            x = pdu[2:4]
            y = b2h(b)
            if x == y:
                break
            elif b != '\x60':
                # Ok, it 'could' be SW1
                sw1 = b
                sw2 = self._rx_byte()
                nil = self._rx_byte()
                if (sw2 and not nil):
                    return '', b2h(sw1 + sw2)

                raise ProtocolError()

        # Send data (if any)
        if len(pdu) > 5:
            pdu2 = pdu1[5:]
            self._tx_string(pdu2)

        # Receive data (including SW !)
        #  length = [P3 - tx_data (=len(pdu)-len(hdr)) + 2 (SW1/2) ]
        to_recv = data_len - len(pdu) / 2 + 5 + 4
        to_recv = data_len + 2

        data = ''
        while (len(data) / 2 < to_recv + 1):
            b = self._rx_byte()
            if (to_recv == 2) and (
                    b == '\x60'):  # Ignore NIL if we have no RX data (hack ?)
                continue
            if not b:
                break
            data += b2h(b)

        # Split datafield from SW
        if len(data) < 4:
            return None, None
        sw = data[-4:]
        data = data[0:-4]

        self._dbg_print("SW: " + sw)
        self._dbg_print("Data: " + data)
        # Return value
        return data, sw