| Index: content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
 | 
| diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
 | 
| index 50f1dbbbd06c34269313ca06338b688815988bb0..1cd9b2c512ea43deed78287e16a54f3056faf2e8 100644
 | 
| --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
 | 
| +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
 | 
| @@ -57,10 +57,13 @@ GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
 | 
|        xinput_available_(GetXInputDllFunctions()) {
 | 
|    for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i)
 | 
|      pad_state_[i].status = DISCONNECTED;
 | 
| +
 | 
| +  raw_input_fetcher_.reset(new RawInputDataFetcher());
 | 
| +  raw_input_fetcher_->StartMonitor();
 | 
|  }
 | 
|  
 | 
|  GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() {
 | 
| -
 | 
| +  raw_input_fetcher_->StopMonitor();
 | 
|  }
 | 
|  
 | 
|  int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const {
 | 
| @@ -80,6 +83,16 @@ bool GamepadPlatformDataFetcherWin::HasXInputGamepad(int index) const {
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
| +bool GamepadPlatformDataFetcherWin::HasRawInputGamepad(
 | 
| +    const HANDLE handle) const {
 | 
| +  for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
 | 
| +    if (pad_state_[i].status == RAWINPUT_CONNECTED &&
 | 
| +        pad_state_[i].raw_input_handle == handle)
 | 
| +      return true;
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
|  void GamepadPlatformDataFetcherWin::EnumerateDevices(
 | 
|      WebGamepads* pads) {
 | 
|    TRACE_EVENT0("GAMEPAD", "EnumerateDevices");
 | 
| @@ -100,6 +113,36 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices(
 | 
|      if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) {
 | 
|        pad_state_[pad_index].status = XINPUT_CONNECTED;
 | 
|        pad_state_[pad_index].xinput_index = i;
 | 
| +      pad_state_[pad_index].mapper = NULL;
 | 
| +      pads->length++;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  if (raw_input_fetcher_->Available()) {
 | 
| +    std::vector<RawGamepadInfo*> raw_inputs =
 | 
| +        raw_input_fetcher_->EnumerateDevices();
 | 
| +    for (size_t i = 0; i < raw_inputs.size(); ++i) {
 | 
| +      RawGamepadInfo* gamepad = raw_inputs[i];
 | 
| +      if (HasRawInputGamepad(gamepad->handle))
 | 
| +        continue;
 | 
| +      int pad_index = FirstAvailableGamepadId();
 | 
| +      if (pad_index == -1)
 | 
| +        return;
 | 
| +      WebGamepad& pad = pads->items[pad_index];
 | 
| +      pad.connected = true;
 | 
| +      PadState& state = pad_state_[pad_index];
 | 
| +      state.status = RAWINPUT_CONNECTED;
 | 
| +      state.raw_input_handle = gamepad->handle;
 | 
| +
 | 
| +      std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id);
 | 
| +      std::string product = base::StringPrintf("%04x", gamepad->product_id);
 | 
| +      state.mapper = GetGamepadStandardMappingFunction(vendor, product);
 | 
| +
 | 
| +      swprintf(pad.id, WebGamepad::idLengthCap,
 | 
| +        L"%ls (%lsVendor: %04x Product: %04x)",
 | 
| +        gamepad->id, state.mapper ? L"STANDARD GAMEPAD " : L"",
 | 
| +        gamepad->vendor_id, gamepad->product_id);
 | 
| +      pads->length++;
 | 
|      }
 | 
|    }
 | 
|  }
 | 
| @@ -109,7 +152,8 @@ void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
 | 
|                                                     bool devices_changed_hint) {
 | 
|    TRACE_EVENT0("GAMEPAD", "GetGamepadData");
 | 
|  
 | 
| -  if (!xinput_available_) {
 | 
| +  if (!xinput_available_ &&
 | 
| +      !raw_input_fetcher_->Available()) {
 | 
|      pads->length = 0;
 | 
|      return;
 | 
|    }
 | 
| @@ -125,11 +169,24 @@ void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
 | 
|      EnumerateDevices(pads);
 | 
|  
 | 
|    for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
 | 
| -    WebGamepad& pad = pads->items[i];
 | 
| +    // We rely on device_changed and GetCapabilities to tell us that
 | 
| +    // something's been connected, but we will mark as disconnected if
 | 
| +    // Get___PadState returns that we've lost the pad.
 | 
| +    if (!pads->items[i].connected)
 | 
| +      continue;
 | 
| +
 | 
|      if (pad_state_[i].status == XINPUT_CONNECTED)
 | 
| -      GetXInputPadData(i, &pad);
 | 
| +      GetXInputPadData(i, &pads->items[i]);
 | 
| +    else if (pad_state_[i].status == RAWINPUT_CONNECTED)
 | 
| +      GetRawInputPadData(i, &pads->items[i]);
 | 
|    }
 | 
| -  pads->length = WebGamepads::itemsLengthCap;
 | 
| +}
 | 
| +
 | 
| +void GamepadPlatformDataFetcherWin::PauseHint(bool pause) {
 | 
| +  if (pause)
 | 
| +    raw_input_fetcher_->StopMonitor();
 | 
| +  else
 | 
| +    raw_input_fetcher_->StartMonitor();
 | 
|  }
 | 
|  
 | 
|  bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
 | 
| @@ -155,12 +212,6 @@ bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
 | 
|  void GamepadPlatformDataFetcherWin::GetXInputPadData(
 | 
|      int i,
 | 
|      WebGamepad* pad) {
 | 
| -  // We rely on device_changed and GetCapabilities to tell us that
 | 
| -  // something's been connected, but we will mark as disconnected if
 | 
| -  // GetState returns that we've lost the pad.
 | 
| -  if (!pad->connected)
 | 
| -    return;
 | 
| -
 | 
|    XINPUT_STATE state;
 | 
|    memset(&state, 0, sizeof(XINPUT_STATE));
 | 
|    TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i);
 | 
| @@ -200,6 +251,36 @@ void GamepadPlatformDataFetcherWin::GetXInputPadData(
 | 
|    }
 | 
|  }
 | 
|  
 | 
| +void GamepadPlatformDataFetcherWin::GetRawInputPadData(
 | 
| +    int index,
 | 
| +    WebGamepad* pad) {
 | 
| +  RawGamepadInfo* gamepad = raw_input_fetcher_->GetGamepadInfo(
 | 
| +      pad_state_[index].raw_input_handle);
 | 
| +  if (!gamepad) {
 | 
| +    pad->connected = false;
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  WebGamepad raw_pad = *pad;
 | 
| +
 | 
| +  raw_pad.timestamp = gamepad->report_id;
 | 
| +  raw_pad.buttonsLength = gamepad->buttons_length;
 | 
| +  raw_pad.axesLength =  gamepad->axes_length;
 | 
| +
 | 
| +  for (unsigned int i = 0; i < raw_pad.buttonsLength; i++)
 | 
| +    raw_pad.buttons[i] = gamepad->buttons[i] ? 1.0 : 0.0;
 | 
| +
 | 
| +  for (unsigned int i = 0; i < raw_pad.axesLength; i++)
 | 
| +    raw_pad.axes[i] = gamepad->axes[i].value;
 | 
| +
 | 
| +  // Copy to the current state to the output buffer, using the mapping
 | 
| +  // function, if there is one available.
 | 
| +  if (pad_state_[index].mapper)
 | 
| +    pad_state_[index].mapper(raw_pad, pad);
 | 
| +  else
 | 
| +    *pad = raw_pad;
 | 
| +}
 | 
| +
 | 
|  bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
 | 
|    xinput_get_capabilities_ = NULL;
 | 
|    xinput_get_state_ = NULL;
 | 
| 
 |