adb_winusb_io_completion.cpp revision f855c4e8469e31114fccca4c28aeb01a806a9a48
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/** \file
18  This file consists of implementation of class AdbWinUsbIOCompletion that
19  encapsulates a wrapper around OVERLAPPED Win32 structure returned from
20  asynchronous I/O requests issued via WinUsb API.
21*/
22
23#include "stdafx.h"
24#include "adb_winusb_io_completion.h"
25
26AdbWinUsbIOCompletion::AdbWinUsbIOCompletion(
27    AdbWinUsbEndpointObject* parent_io_obj,
28    ULONG expected_trans_size,
29    HANDLE event_hndl)
30    : AdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl) {
31}
32
33AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() {
34}
35
36LONG AdbWinUsbIOCompletion::Release() {
37  ATLASSERT(ref_count_ > 0);
38  LONG ret = InterlockedDecrement(&ref_count_);
39  ATLASSERT(ret >= 0);
40  if (0 == ret) {
41    LastReferenceReleased();
42    delete this;
43  }
44  return ret;
45}
46
47bool AdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,
48                                                 ULONG* bytes_transferred,
49                                                 bool wait) {
50  if (NULL != bytes_transferred) {
51    *bytes_transferred = 0;
52  }
53
54  if (!IsOpened()) {
55    SetLastError(ERROR_INVALID_HANDLE);
56    return false;
57  }
58
59  ULONG transfer;
60  bool ret = WinUsb_GetOverlappedResult(
61                  parent_winusb_io_object()->winusb_handle(),
62                  overlapped(),
63                  &transfer,
64                  wait ? TRUE : FALSE) ? true : false;
65
66  // TODO: This is bizzare but I've seen it happening
67  // that GetOverlappedResult with wait set to true returns "prematurely",
68  // with wrong transferred bytes value and GetLastError reporting
69  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!
70  ULONG error = GetLastError();
71
72  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&
73      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {
74    for (int trying = 0; trying < 10; trying++) {
75      Sleep(2);
76      ret = WinUsb_GetOverlappedResult(
77                parent_winusb_io_object()->winusb_handle(),
78                overlapped(),
79                &transfer,
80                wait ? TRUE : FALSE) ? true : false;
81      error = GetLastError();
82      if (!ret || (0 != transfer) ||
83          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {
84        break;
85      }
86    }
87  }
88
89  if (NULL != ovl_data) {
90    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));
91  }
92
93  if (NULL != bytes_transferred) {
94    *bytes_transferred = transfer;
95  }
96
97  return ret;
98}
99