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