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 
AdbWinUsbIOCompletion(AdbWinUsbEndpointObject * parent_io_obj,ULONG expected_trans_size,HANDLE event_hndl)26 AdbWinUsbIOCompletion::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 
~AdbWinUsbIOCompletion()33 AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() {
34 }
35 
Release()36 LONG 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 
GetOvelappedIoResult(LPOVERLAPPED ovl_data,ULONG * bytes_transferred,bool wait)47 bool 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