adb_winusb_endpoint_object.cpp revision f855c4e8469e31114fccca4c28aeb01a806a9a48
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 AdbWinUsbEndpointObject that
19  encapsulates a handle opened to a WinUsb endpoint on our device.
20*/
21
22#include "stdafx.h"
23#include "adb_winusb_endpoint_object.h"
24#include "adb_winusb_io_completion.h"
25
26AdbWinUsbEndpointObject::AdbWinUsbEndpointObject(
27    AdbWinUsbInterfaceObject* parent_interf,
28    UCHAR endpoint_id,
29    UCHAR endpoint_index)
30    : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) {
31}
32
33AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() {
34}
35
36LONG AdbWinUsbEndpointObject::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
47ADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite(
48    bool is_read,
49    void* buffer,
50    ULONG bytes_to_transfer,
51    ULONG* bytes_transferred,
52    HANDLE event_handle,
53    ULONG time_out) {
54  if (!SetTimeout(time_out))
55    return false;
56
57  // Create completion i/o object
58  AdbIOCompletion* adb_io_completion = NULL;
59
60  try {
61    adb_io_completion = new AdbWinUsbIOCompletion(this,
62                                                  bytes_to_transfer,
63                                                  event_handle);
64  } catch (... ) {
65    SetLastError(ERROR_OUTOFMEMORY);
66    return NULL;
67  }
68
69  // Create a handle for it
70  ADBAPIHANDLE ret = adb_io_completion->CreateHandle();
71  ULONG transferred = 0;
72  if (NULL != ret) {
73    BOOL res = TRUE;
74    // Go the read / write file way
75    res = is_read ?
76        WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(),
77                        endpoint_id(),
78                        reinterpret_cast<PUCHAR>(buffer),
79                        bytes_to_transfer,
80                        &transferred,
81                        adb_io_completion->overlapped()) :
82        WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
83                         endpoint_id(),
84                         reinterpret_cast<PUCHAR>(buffer),
85                         bytes_to_transfer,
86                         &transferred,
87                         adb_io_completion->overlapped());
88
89    if (NULL != bytes_transferred)
90      *bytes_transferred = transferred;
91
92    ULONG error = GetLastError();
93    if (!res && (ERROR_IO_PENDING != error)) {
94      // I/O failed immediatelly. We need to close i/o completion object
95      // before we return NULL to the caller.
96      adb_io_completion->CloseHandle();
97      ret = NULL;
98      SetLastError(error);
99    }
100  }
101
102  // Offseting 'new'
103  adb_io_completion->Release();
104
105  return ret;
106}
107
108bool AdbWinUsbEndpointObject::CommonSyncReadWrite(bool is_read,
109                                                  void* buffer,
110                                                  ULONG bytes_to_transfer,
111                                                  ULONG* bytes_transferred,
112                                                  ULONG time_out) {
113  if (!SetTimeout(time_out))
114    return false;
115
116  // This is synchronous I/O. Since we always open I/O items for
117  // overlapped I/O we're obligated to always provide OVERLAPPED
118  // structure to read / write routines. Prepare it now.
119  OVERLAPPED overlapped;
120  ZeroMemory(&overlapped, sizeof(overlapped));
121  overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
122
123  BOOL ret = TRUE;
124  ULONG transferred = 0;
125  // Go the read / write file way
126  ret = is_read ?
127        WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(),
128                        endpoint_id(),
129                        reinterpret_cast<PUCHAR>(buffer),
130                        bytes_to_transfer,
131                        &transferred,
132                        &overlapped) :
133        WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
134                         endpoint_id(),
135                         reinterpret_cast<PUCHAR>(buffer),
136                         bytes_to_transfer,
137                         &transferred,
138                         &overlapped);
139
140  // Lets see the result
141  if (!ret && (ERROR_IO_PENDING != GetLastError())) {
142    // I/O failed.
143    if (NULL != overlapped.hEvent)
144      ::CloseHandle(overlapped.hEvent);
145    return false;
146  }
147
148  // Lets wait till I/O completes
149  ret = WinUsb_GetOverlappedResult(parent_winusb_interface()->winusb_handle(), &overlapped,
150                                   &transferred, TRUE);
151  if (ret && (NULL != bytes_transferred)) {
152    *bytes_transferred = transferred;
153  }
154
155  if (NULL != overlapped.hEvent)
156    ::CloseHandle(overlapped.hEvent);
157
158  return ret ? true : false;
159}
160
161bool AdbWinUsbEndpointObject::SetTimeout(ULONG timeout) {
162  if (!WinUsb_SetPipePolicy(parent_winusb_interface()->winusb_handle(),
163                            endpoint_id(), PIPE_TRANSFER_TIMEOUT,
164                            sizeof(ULONG), &timeout)) {
165    return false;
166  }
167
168  return true;
169}
170