import struct

def parse_btsnoop(filepath):
    with open(filepath, 'rb') as f:
        header = f.read(16)
        magic = header[:8]
        version = struct.unpack('>I', header[8:12])[0]
        datalink = struct.unpack('>I', header[12:16])[0]
        print(f"Magic: {magic}, Version: {version}, Datalink: {datalink}")
        
        pkt_num = 0
        ble_writes = []
        pkt_types = {}
        flag_types = {}
        
        while True:
            pkt_hdr = f.read(24)
            if len(pkt_hdr) < 24:
                break
            
            orig_len, inc_len, flags, drops, ts = struct.unpack('>IIIIq', pkt_hdr)
            data = f.read(inc_len)
            if len(data) < inc_len:
                break
            
            pkt_num += 1
            
            # Track flag values
            flag_key = flags
            flag_types[flag_key] = flag_types.get(flag_key, 0) + 1
            
            direction = "SENT" if (flags & 1) == 0 else "RECV"
            pkt_type = (flags >> 1) & 0x07
            
            # For ACL data (type 1 = sent ACL, type 4 = received ACL)
            if pkt_type in (1, 4) and len(data) >= 9:
                # ACL header
                acl_hdr = struct.unpack('<HH', data[:4])
                # L2CAP header
                l2cap = struct.unpack('<HH', data[4:8])
                cid = l2cap[1]
                
                if cid == 4 and len(data) > 8:  # ATT
                    att_opcode = data[8]
                    if att_opcode in (0x52, 0x12):
                        att_handle = struct.unpack('<H', data[9:11])[0] if len(data) > 10 else None
                        payload = data[11:] if len(data) > 11 else b''
                        ble_writes.append({
                            'dir': direction,
                            'opcode': f'0x{att_opcode:02x}',
                            'handle': f'0x{att_handle:04x}' if att_handle else None,
                            'payload': payload.hex(),
                            'payload_len': len(payload),
                        })
        
        print(f"\nTotal packets: {pkt_num}")
        print(f"Flag distributions: {flag_types}")
        print(f"BLE writes found: {len(ble_writes)}")
        
        if ble_writes:
            print(f"\n--- BLE Write Commands ---")
            for i, w in enumerate(ble_writes):
                print(f"[{i:3d}] {w['dir']} {w['opcode']} handle={w['handle']} len={w['payload_len']} payload={w['payload']}")
        else:
            # Try to find any interesting patterns in the data
            print("\nNo BLE writes found. Dumping first 20 packets:")
            f.seek(16)  # reset to after header
            for i in range(min(20, pkt_num)):
                pkt_hdr = f.read(24)
                if len(pkt_hdr) < 24:
                    break
                orig_len, inc_len, flags, drops, ts = struct.unpack('>IIIIq', pkt_hdr)
                data = f.read(inc_len)
                if len(data) < inc_len:
                    break
                direction = "SENT" if (flags & 1) == 0 else "RECV"
                pkt_type = (flags >> 1) & 0x07
                print(f"  [{i}] flags=0x{flags:08x} type={pkt_type} dir={direction} len={inc_len} data={data[:20].hex()}")
        
        return ble_writes

writes = parse_btsnoop('/tmp/FS/data/misc/bluetooth/logs/btsnooz_hci.log')
