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
AdbWinUsbEndpointObject(AdbWinUsbInterfaceObject * parent_interf,UCHAR endpoint_id,UCHAR endpoint_index)26 AdbWinUsbEndpointObject::AdbWinUsbEndpointObject(
27 AdbWinUsbInterfaceObject* parent_interf,
28 UCHAR endpoint_id,
29 UCHAR endpoint_index)
30 : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) {
31 }
32
~AdbWinUsbEndpointObject()33 AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() {
34 }
35
Release()36 LONG 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
CommonAsyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,HANDLE event_handle,ULONG time_out)47 ADBAPIHANDLE 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
CommonSyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,ULONG time_out)108 bool 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
SetTimeout(ULONG timeout)161 bool 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