The goal of jointly providing fairness and efficiency in wireless networks can be seen as the problem of maximizing a given utility function. The main difficulty when solving this problem is that the capacity region of wireless networks is typically unknown and time-varying, which prevents the usage of traditional optimization tools. As a result, scheduling and congestion control algorithms are either too conservative because they under-estimate the capacity region, or suffer from congestion collapse because they over-estimate it. We propose a new adaptive congestion control algorithm, called Enhance & Explore (E&E). It maximizes the utility of the network without requiring any explicit characterization of the capacity region. E&E works above the MAC layer and is decoupled from the underlying scheduling mechanism. It provably converges to a state of optimal utility. We evaluate the performance of the algorithm in a WLAN setting, using both simulations and measurements on a real testbed composed of IEEE 802.11 wireless routers.