18267511c96e3226e45a0be773ee442b66261824dvchtchetkine/*
28267511c96e3226e45a0be773ee442b66261824dvchtchetkine * Copyright (C) 2009 The Android Open Source Project
38267511c96e3226e45a0be773ee442b66261824dvchtchetkine *
48267511c96e3226e45a0be773ee442b66261824dvchtchetkine * Licensed under the Apache License, Version 2.0 (the "License");
58267511c96e3226e45a0be773ee442b66261824dvchtchetkine * you may not use this file except in compliance with the License.
68267511c96e3226e45a0be773ee442b66261824dvchtchetkine * You may obtain a copy of the License at
78267511c96e3226e45a0be773ee442b66261824dvchtchetkine *
88267511c96e3226e45a0be773ee442b66261824dvchtchetkine *      http://www.apache.org/licenses/LICENSE-2.0
98267511c96e3226e45a0be773ee442b66261824dvchtchetkine *
108267511c96e3226e45a0be773ee442b66261824dvchtchetkine * Unless required by applicable law or agreed to in writing, software
118267511c96e3226e45a0be773ee442b66261824dvchtchetkine * distributed under the License is distributed on an "AS IS" BASIS,
128267511c96e3226e45a0be773ee442b66261824dvchtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138267511c96e3226e45a0be773ee442b66261824dvchtchetkine * See the License for the specific language governing permissions and
148267511c96e3226e45a0be773ee442b66261824dvchtchetkine * limitations under the License.
158267511c96e3226e45a0be773ee442b66261824dvchtchetkine */
168267511c96e3226e45a0be773ee442b66261824dvchtchetkine
178267511c96e3226e45a0be773ee442b66261824dvchtchetkine/** \file
188267511c96e3226e45a0be773ee442b66261824dvchtchetkine  This file consists of implementation of class AdbWinUsbEndpointObject that
198267511c96e3226e45a0be773ee442b66261824dvchtchetkine  encapsulates a handle opened to a WinUsb endpoint on our device.
208267511c96e3226e45a0be773ee442b66261824dvchtchetkine*/
218267511c96e3226e45a0be773ee442b66261824dvchtchetkine
228267511c96e3226e45a0be773ee442b66261824dvchtchetkine#include "stdafx.h"
238267511c96e3226e45a0be773ee442b66261824dvchtchetkine#include "adb_winusb_endpoint_object.h"
248267511c96e3226e45a0be773ee442b66261824dvchtchetkine#include "adb_winusb_io_completion.h"
258267511c96e3226e45a0be773ee442b66261824dvchtchetkine
268267511c96e3226e45a0be773ee442b66261824dvchtchetkineAdbWinUsbEndpointObject::AdbWinUsbEndpointObject(
278267511c96e3226e45a0be773ee442b66261824dvchtchetkine    AdbWinUsbInterfaceObject* parent_interf,
288267511c96e3226e45a0be773ee442b66261824dvchtchetkine    UCHAR endpoint_id,
298267511c96e3226e45a0be773ee442b66261824dvchtchetkine    UCHAR endpoint_index)
308267511c96e3226e45a0be773ee442b66261824dvchtchetkine    : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) {
318267511c96e3226e45a0be773ee442b66261824dvchtchetkine}
328267511c96e3226e45a0be773ee442b66261824dvchtchetkine
338267511c96e3226e45a0be773ee442b66261824dvchtchetkineAdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() {
348267511c96e3226e45a0be773ee442b66261824dvchtchetkine}
358267511c96e3226e45a0be773ee442b66261824dvchtchetkine
36acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkineLONG AdbWinUsbEndpointObject::Release() {
37acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  ATLASSERT(ref_count_ > 0);
38acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  LONG ret = InterlockedDecrement(&ref_count_);
39acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  ATLASSERT(ret >= 0);
40acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  if (0 == ret) {
41acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine    LastReferenceReleased();
42acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine    delete this;
43acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  }
44acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine  return ret;
45acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine}
46acc6f826433e639b1ba00c021ab5f9161eb56e59vchtchetkine
478267511c96e3226e45a0be773ee442b66261824dvchtchetkineADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite(
488267511c96e3226e45a0be773ee442b66261824dvchtchetkine    bool is_read,
498267511c96e3226e45a0be773ee442b66261824dvchtchetkine    void* buffer,
508267511c96e3226e45a0be773ee442b66261824dvchtchetkine    ULONG bytes_to_transfer,
518267511c96e3226e45a0be773ee442b66261824dvchtchetkine    ULONG* bytes_transferred,
528267511c96e3226e45a0be773ee442b66261824dvchtchetkine    HANDLE event_handle,
538267511c96e3226e45a0be773ee442b66261824dvchtchetkine    ULONG time_out) {
548267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (!SetTimeout(time_out))
558267511c96e3226e45a0be773ee442b66261824dvchtchetkine    return false;
568267511c96e3226e45a0be773ee442b66261824dvchtchetkine
578267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Create completion i/o object
588267511c96e3226e45a0be773ee442b66261824dvchtchetkine  AdbIOCompletion* adb_io_completion = NULL;
598267511c96e3226e45a0be773ee442b66261824dvchtchetkine
608267511c96e3226e45a0be773ee442b66261824dvchtchetkine  try {
618267511c96e3226e45a0be773ee442b66261824dvchtchetkine    adb_io_completion = new AdbWinUsbIOCompletion(this,
628267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  bytes_to_transfer,
638267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  event_handle);
648267511c96e3226e45a0be773ee442b66261824dvchtchetkine  } catch (... ) {
658267511c96e3226e45a0be773ee442b66261824dvchtchetkine    SetLastError(ERROR_OUTOFMEMORY);
668267511c96e3226e45a0be773ee442b66261824dvchtchetkine    return NULL;
678267511c96e3226e45a0be773ee442b66261824dvchtchetkine  }
688267511c96e3226e45a0be773ee442b66261824dvchtchetkine
698267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Create a handle for it
708267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ADBAPIHANDLE ret = adb_io_completion->CreateHandle();
718267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ULONG transferred = 0;
728267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (NULL != ret) {
738267511c96e3226e45a0be773ee442b66261824dvchtchetkine    BOOL res = TRUE;
748267511c96e3226e45a0be773ee442b66261824dvchtchetkine    // Go the read / write file way
758267511c96e3226e45a0be773ee442b66261824dvchtchetkine    res = is_read ?
768267511c96e3226e45a0be773ee442b66261824dvchtchetkine        WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(),
778267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        endpoint_id(),
788267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        reinterpret_cast<PUCHAR>(buffer),
798267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        bytes_to_transfer,
808267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        &transferred,
818267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        adb_io_completion->overlapped()) :
828267511c96e3226e45a0be773ee442b66261824dvchtchetkine        WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
838267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         endpoint_id(),
848267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         reinterpret_cast<PUCHAR>(buffer),
858267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         bytes_to_transfer,
868267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         &transferred,
878267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         adb_io_completion->overlapped());
888267511c96e3226e45a0be773ee442b66261824dvchtchetkine
898267511c96e3226e45a0be773ee442b66261824dvchtchetkine    if (NULL != bytes_transferred)
908267511c96e3226e45a0be773ee442b66261824dvchtchetkine      *bytes_transferred = transferred;
918267511c96e3226e45a0be773ee442b66261824dvchtchetkine
928267511c96e3226e45a0be773ee442b66261824dvchtchetkine    ULONG error = GetLastError();
938267511c96e3226e45a0be773ee442b66261824dvchtchetkine    if (!res && (ERROR_IO_PENDING != error)) {
948267511c96e3226e45a0be773ee442b66261824dvchtchetkine      // I/O failed immediatelly. We need to close i/o completion object
958267511c96e3226e45a0be773ee442b66261824dvchtchetkine      // before we return NULL to the caller.
968267511c96e3226e45a0be773ee442b66261824dvchtchetkine      adb_io_completion->CloseHandle();
978267511c96e3226e45a0be773ee442b66261824dvchtchetkine      ret = NULL;
988267511c96e3226e45a0be773ee442b66261824dvchtchetkine      SetLastError(error);
998267511c96e3226e45a0be773ee442b66261824dvchtchetkine    }
1008267511c96e3226e45a0be773ee442b66261824dvchtchetkine  }
1018267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1028267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Offseting 'new'
1038267511c96e3226e45a0be773ee442b66261824dvchtchetkine  adb_io_completion->Release();
1048267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1058267511c96e3226e45a0be773ee442b66261824dvchtchetkine  return ret;
1068267511c96e3226e45a0be773ee442b66261824dvchtchetkine}
1078267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1088267511c96e3226e45a0be773ee442b66261824dvchtchetkinebool AdbWinUsbEndpointObject::CommonSyncReadWrite(bool is_read,
1098267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  void* buffer,
1108267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  ULONG bytes_to_transfer,
1118267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  ULONG* bytes_transferred,
1128267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                                  ULONG time_out) {
1138267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (!SetTimeout(time_out))
1148267511c96e3226e45a0be773ee442b66261824dvchtchetkine    return false;
1158267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1168267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // This is synchronous I/O. Since we always open I/O items for
1178267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // overlapped I/O we're obligated to always provide OVERLAPPED
1188267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // structure to read / write routines. Prepare it now.
1198267511c96e3226e45a0be773ee442b66261824dvchtchetkine  OVERLAPPED overlapped;
1208267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ZeroMemory(&overlapped, sizeof(overlapped));
1218267511c96e3226e45a0be773ee442b66261824dvchtchetkine  overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1228267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1238267511c96e3226e45a0be773ee442b66261824dvchtchetkine  BOOL ret = TRUE;
1248267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ULONG transferred = 0;
1258267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Go the read / write file way
1268267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ret = is_read ?
1278267511c96e3226e45a0be773ee442b66261824dvchtchetkine        WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(),
1288267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        endpoint_id(),
1298267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        reinterpret_cast<PUCHAR>(buffer),
1308267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        bytes_to_transfer,
1318267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        &transferred,
1328267511c96e3226e45a0be773ee442b66261824dvchtchetkine                        &overlapped) :
1338267511c96e3226e45a0be773ee442b66261824dvchtchetkine        WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
1348267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         endpoint_id(),
1358267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         reinterpret_cast<PUCHAR>(buffer),
1368267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         bytes_to_transfer,
1378267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         &transferred,
1388267511c96e3226e45a0be773ee442b66261824dvchtchetkine                         &overlapped);
1398267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1408267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Lets see the result
1418267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (!ret && (ERROR_IO_PENDING != GetLastError())) {
1428267511c96e3226e45a0be773ee442b66261824dvchtchetkine    // I/O failed.
1438267511c96e3226e45a0be773ee442b66261824dvchtchetkine    if (NULL != overlapped.hEvent)
1448267511c96e3226e45a0be773ee442b66261824dvchtchetkine      ::CloseHandle(overlapped.hEvent);
1458267511c96e3226e45a0be773ee442b66261824dvchtchetkine    return false;
1468267511c96e3226e45a0be773ee442b66261824dvchtchetkine  }
1478267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1488267511c96e3226e45a0be773ee442b66261824dvchtchetkine  // Lets wait till I/O completes
1498267511c96e3226e45a0be773ee442b66261824dvchtchetkine  ret = WinUsb_GetOverlappedResult(parent_winusb_interface()->winusb_handle(), &overlapped,
1508267511c96e3226e45a0be773ee442b66261824dvchtchetkine                                   &transferred, TRUE);
1518267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (ret && (NULL != bytes_transferred)) {
1528267511c96e3226e45a0be773ee442b66261824dvchtchetkine    *bytes_transferred = transferred;
1538267511c96e3226e45a0be773ee442b66261824dvchtchetkine  }
1548267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1558267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (NULL != overlapped.hEvent)
1568267511c96e3226e45a0be773ee442b66261824dvchtchetkine    ::CloseHandle(overlapped.hEvent);
1578267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1588267511c96e3226e45a0be773ee442b66261824dvchtchetkine  return ret ? true : false;
1598267511c96e3226e45a0be773ee442b66261824dvchtchetkine}
1608267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1618267511c96e3226e45a0be773ee442b66261824dvchtchetkinebool AdbWinUsbEndpointObject::SetTimeout(ULONG timeout) {
1628267511c96e3226e45a0be773ee442b66261824dvchtchetkine  if (!WinUsb_SetPipePolicy(parent_winusb_interface()->winusb_handle(),
1638267511c96e3226e45a0be773ee442b66261824dvchtchetkine                            endpoint_id(), PIPE_TRANSFER_TIMEOUT,
1648267511c96e3226e45a0be773ee442b66261824dvchtchetkine                            sizeof(ULONG), &timeout)) {
1658267511c96e3226e45a0be773ee442b66261824dvchtchetkine    return false;
1668267511c96e3226e45a0be773ee442b66261824dvchtchetkine  }
1678267511c96e3226e45a0be773ee442b66261824dvchtchetkine
1688267511c96e3226e45a0be773ee442b66261824dvchtchetkine  return true;
1698267511c96e3226e45a0be773ee442b66261824dvchtchetkine}
170