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 AdbLegacyEndpointObject that
19 encapsulates a handle opened to an endpoint on our device controlled by
20 a custom (legacy) USB driver.
21 */
22
23 #include "stdafx.h"
24 #include "adb_api_legacy.h"
25 #include "adb_legacy_endpoint_object.h"
26 #include "adb_legacy_io_completion.h"
27 #include "adb_helper_routines.h"
28
AdbLegacyEndpointObject(AdbLegacyInterfaceObject * parent_interf,UCHAR endpoint_id,UCHAR endpoint_index)29 AdbLegacyEndpointObject::AdbLegacyEndpointObject(
30 AdbLegacyInterfaceObject* parent_interf,
31 UCHAR endpoint_id,
32 UCHAR endpoint_index)
33 : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index),
34 usb_handle_(INVALID_HANDLE_VALUE) {
35 }
36
~AdbLegacyEndpointObject()37 AdbLegacyEndpointObject::~AdbLegacyEndpointObject() {
38 if (INVALID_HANDLE_VALUE != usb_handle_) {
39 ::CloseHandle(usb_handle_);
40 }
41 }
42
CommonAsyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,HANDLE event_handle,ULONG time_out)43 ADBAPIHANDLE AdbLegacyEndpointObject::CommonAsyncReadWrite(
44 bool is_read,
45 void* buffer,
46 ULONG bytes_to_transfer,
47 ULONG* bytes_transferred,
48 HANDLE event_handle,
49 ULONG time_out) {
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 bool is_ioctl_write = is_read ? false : (0 != time_out);
60
61 // Create completion i/o object
62 AdbLegacyIOCompletion* adb_io_completion = NULL;
63
64 try {
65 adb_io_completion = new AdbLegacyIOCompletion(this,
66 bytes_to_transfer,
67 event_handle,
68 is_ioctl_write);
69 } catch (... ) {
70 // We don't expect exceptions other than OOM thrown here.
71 SetLastError(ERROR_OUTOFMEMORY);
72 return NULL;
73 }
74
75 // Create a handle for it
76 ADBAPIHANDLE ret = adb_io_completion->CreateHandle();
77 ULONG transferred = 0;
78 if (NULL != ret) {
79 BOOL res = TRUE;
80 if (0 == time_out) {
81 // Go the read / write file way
82 res = is_read ? ReadFile(usb_handle(),
83 buffer,
84 bytes_to_transfer,
85 &transferred,
86 adb_io_completion->overlapped()) :
87 WriteFile(usb_handle(),
88 buffer,
89 bytes_to_transfer,
90 &transferred,
91 adb_io_completion->overlapped());
92 } else {
93 // Go IOCTL way
94 AdbBulkTransfer transfer_param;
95 transfer_param.time_out = time_out;
96 transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
97 transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
98
99 res = DeviceIoControl(usb_handle(),
100 is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
101 &transfer_param, sizeof(transfer_param),
102 is_read ? buffer : adb_io_completion->transferred_bytes_ptr(),
103 is_read ? bytes_to_transfer : sizeof(ULONG),
104 &transferred,
105 adb_io_completion->overlapped());
106 }
107
108 if (NULL != bytes_transferred) {
109 *bytes_transferred = transferred;
110 }
111
112 ULONG error = GetLastError();
113 if (!res && (ERROR_IO_PENDING != error)) {
114 // I/O failed immediatelly. We need to close i/o completion object
115 // before we return NULL to the caller.
116 adb_io_completion->CloseHandle();
117 ret = NULL;
118 SetLastError(error);
119 }
120 }
121
122 // Offseting 'new'
123 adb_io_completion->Release();
124
125 return ret;
126 }
127
CommonSyncReadWrite(bool is_read,void * buffer,ULONG bytes_to_transfer,ULONG * bytes_transferred,ULONG time_out)128 bool AdbLegacyEndpointObject::CommonSyncReadWrite(bool is_read,
129 void* buffer,
130 ULONG bytes_to_transfer,
131 ULONG* bytes_transferred,
132 ULONG time_out) {
133 if (NULL != bytes_transferred) {
134 *bytes_transferred = 0;
135 }
136
137 if (!IsOpened()) {
138 SetLastError(ERROR_INVALID_HANDLE);
139 return false;
140 }
141
142 bool is_ioctl_write = is_read ? false : (0 != time_out);
143
144 // This is synchronous I/O. Since we always open I/O items for
145 // overlapped I/O we're obligated to always provide OVERLAPPED
146 // structure to read / write routines. Prepare it now.
147 OVERLAPPED overlapped;
148 ZeroMemory(&overlapped, sizeof(overlapped));
149
150 BOOL ret = TRUE;
151 ULONG ioctl_write_transferred = 0;
152 if (0 == time_out) {
153 // Go the read / write file way
154 ret = is_read ?
155 ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) :
156 WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped);
157 } else {
158 // Go IOCTL way
159 AdbBulkTransfer transfer_param;
160 transfer_param.time_out = time_out;
161 transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
162 transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
163
164 ULONG tmp;
165 ret = DeviceIoControl(usb_handle(),
166 is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
167 &transfer_param, sizeof(transfer_param),
168 is_read ? buffer : &ioctl_write_transferred,
169 is_read ? bytes_to_transfer : sizeof(ULONG),
170 &tmp,
171 &overlapped);
172 }
173
174 // Lets see the result
175 if (!ret && (ERROR_IO_PENDING != GetLastError())) {
176 // I/O failed.
177 return false;
178 }
179
180 // Lets wait till I/O completes
181 ULONG transferred = 0;
182 ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE);
183 if (ret && (NULL != bytes_transferred)) {
184 *bytes_transferred = is_ioctl_write ? ioctl_write_transferred :
185 transferred;
186 }
187
188 return ret ? true : false;
189 }
190
CreateHandle(const wchar_t * item_path,AdbOpenAccessType access_type,AdbOpenSharingMode share_mode)191 ADBAPIHANDLE AdbLegacyEndpointObject::CreateHandle(
192 const wchar_t* item_path,
193 AdbOpenAccessType access_type,
194 AdbOpenSharingMode share_mode) {
195 // Convert access / share parameters into CreateFile - compatible
196 ULONG desired_access;
197 ULONG desired_sharing;
198
199 if (!GetSDKComplientParam(access_type, share_mode,
200 &desired_access, &desired_sharing)) {
201 return NULL;
202 }
203
204 // Open USB handle
205 usb_handle_ = CreateFile(item_path,
206 desired_access,
207 share_mode,
208 NULL,
209 OPEN_EXISTING,
210 FILE_FLAG_OVERLAPPED, // Always overlapped!
211 NULL);
212 if (INVALID_HANDLE_VALUE == usb_handle_) {
213 return NULL;
214 }
215
216 // Create ADB handle
217 ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle();
218
219 if (NULL == ret) {
220 // If creation of ADB handle failed we have to close USB handle too.
221 ULONG error = GetLastError();
222 ::CloseHandle(usb_handle());
223 usb_handle_ = INVALID_HANDLE_VALUE;
224 SetLastError(error);
225 }
226
227 return ret;
228 }
229
CloseHandle()230 bool AdbLegacyEndpointObject::CloseHandle() {
231 if (INVALID_HANDLE_VALUE != usb_handle_) {
232 ::CloseHandle(usb_handle_);
233 usb_handle_ = INVALID_HANDLE_VALUE;
234 }
235
236 return AdbEndpointObject::CloseHandle();
237 }
238