Home | History | Annotate | Download | only in winusb
      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