Slave can't pull I2C low
I2C pins must not be set to output high. You are using push-pull outputs. STM32 can configure them as open-drain outputs. In that case it is not even necessary to change it to input for reading. In reality you would not bit-bang the protocol yourself as the STM32 contains an i2C peripheral.