def parse_bin(path):
    f = open(path, 'rb')

    s = {}  # the current Scale data to apply to next requester
    output = []

    # handlers for various fourCC codes
    methods = {
        'GPS5': parse_gps,
        'GPSU': parse_time,
        'GPSF': parse_fix,
        'GPSP': parse_precision,
        'ACCL': parse_accl,
        'GYRO': parse_gyro,
    }

    d = {'gps': []}  # up to date dictionary, iterate and fill then flush

    while True:
        label = f.read(4)
        if not label:  # eof
            break

        desc = f.read(4)

        # null length
        if '00' == binascii.hexlify(desc[0]):
            continue

        val_size = struct.unpack('>b', desc[1])[0]
        num_values = struct.unpack('>h', desc[2:4])[0]
        length = val_size * num_values

        # print "{} {} of size {} and type {}".format(num_values, label,
        # val_size, desc[0])

        if label == 'DVID':
            if len(d['gps']):  # first one is empty
                output.append(d)
            d = {'gps': []}  # reset

        for i in range(num_values):
            data = f.read(val_size)

            if label in methods:
                methods[label](data, d, s)

            if label == 'SCAL':
                if 2 == val_size:
                    s[i] = struct.unpack('>h', data)[0]
                elif 4 == val_size:
                    s[i] = struct.unpack('>i', data)[0]
                else:
                    raise Exception('unknown scal size')

        # pack
        mod = length % 4
        if mod != 0:
            seek = 4 - mod
            f.read(seek)  # discarded

    return output