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 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 33 AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() { 34 } 35 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 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