Home | History | Annotate | Download | only in api
      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 
     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 
     36 AdbLegacyIOCompletion::~AdbLegacyIOCompletion() {
     37 }
     38 
     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