adb_io_completion.cpp revision 52d4c30ca52320ec92d1d1ddc8db3f07f69c4f98
1/*
2 * Copyright (C) 2006 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 AdbIOCompletion that
19  encapsulates a wrapper around OVERLAPPED Win32 structure returned
20  from asynchronous I/O requests.
21*/
22
23#include "stdafx.h"
24#include "adb_io_completion.h"
25
26AdbIOCompletion::AdbIOCompletion(AdbIOObject* parent_io_obj,
27                                 bool is_write_ctl,
28                                 ULONG expected_trans_size,
29                                 HANDLE event_hndl)
30    : AdbObjectHandle(AdbObjectTypeIoCompletion),
31      transferred_bytes_(0),
32      expected_transfer_size_(expected_trans_size),
33      is_write_ioctl_(is_write_ctl),
34      parent_io_object_(parent_io_obj) {
35  ATLASSERT(NULL != parent_io_obj);
36  parent_io_obj->AddRef();
37  ZeroMemory(&overlapped_, sizeof(overlapped_));
38  overlapped_.hEvent = event_hndl;
39}
40
41AdbIOCompletion::~AdbIOCompletion() {
42  parent_io_object_->Release();
43}
44
45bool AdbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,
46                                           ULONG* bytes_transferred,
47                                           bool wait) {
48  if (NULL != bytes_transferred)
49    *bytes_transferred = 0;
50
51  if (!IsOpened()) {
52    SetLastError(ERROR_INVALID_HANDLE);
53    return false;
54  }
55
56  ULONG transfer;
57  bool ret = GetOverlappedResult(parent_io_object()->usb_handle(),
58                                 overlapped(),
59                                 &transfer,
60                                 wait) ? true :
61                                         false;
62
63  // TODO: This is bizzare but I've seen it happening
64  // that GetOverlappedResult with wait set to true returns "prematurely",
65  // with wrong transferred bytes value and GetLastError reporting
66  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!
67  ULONG error = GetLastError();
68
69  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&
70      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {
71    for (int trying = 0; trying < 10; trying++) {
72      Sleep(2);
73      ret = GetOverlappedResult(parent_io_object()->usb_handle(),
74                                overlapped(),
75                                &transfer,
76                                wait) ? true :
77                                        false;
78      error = GetLastError();
79      if (!ret || (0 != transfer) ||
80          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {
81        break;
82      }
83    }
84  }
85
86  if (NULL != ovl_data)
87    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));
88
89  if (NULL != bytes_transferred)
90    *bytes_transferred = is_write_ioctl() ? transferred_bytes_ : transfer;
91
92  return ret;
93}
94
95bool AdbIOCompletion::IsCompleted() {
96  SetLastError(NO_ERROR);
97  if (!IsOpened()) {
98    SetLastError(ERROR_INVALID_HANDLE);
99    return true;
100  }
101
102  return  HasOverlappedIoCompleted(overlapped()) ? true : false;
103}
104