blob: 9b073a4df582bd9c71226345c0973aecc6614e48 [file] [log] [blame]
vchtchetkinedceaaa52009-07-22 13:34:53 -07001/*
2 * Copyright (C) 2006 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 AdbInterfaceObject that
19 encapsulates an interface on our USB device.
20*/
21
22#include "stdafx.h"
23#include "adb_interface.h"
24#include "adb_endpoint_object.h"
25
26AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name)
27 : AdbObjectHandle(AdbObjectTypeInterface),
28 interface_name_(interf_name),
29 usb_device_handle_(INVALID_HANDLE_VALUE),
30 winusb_handle_(NULL),
31 interface_number_(0xFF),
32 def_read_endpoint_(0xFF),
33 read_endpoint_id_(0xFF),
34 def_write_endpoint_(0xFF),
35 write_endpoint_id_(0xFF) {
36 ATLASSERT(NULL != interf_name);
37}
38
39AdbInterfaceObject::~AdbInterfaceObject() {
40 ATLASSERT(NULL == winusb_handle_);
41 ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);
42}
43
44ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {
45 // Open USB device for this inteface Note that WinUsb API
46 // requires the handle to be opened for overlapped I/O.
47 usb_device_handle_ = CreateFile(interface_name().c_str(),
48 GENERIC_READ | GENERIC_WRITE,
49 FILE_SHARE_READ | FILE_SHARE_WRITE,
50 NULL, OPEN_EXISTING,
51 FILE_FLAG_OVERLAPPED, NULL);
52 if (INVALID_HANDLE_VALUE == usb_device_handle_)
53 return NULL;
54
55 // Initialize WinUSB API for this interface
56 if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))
57 return NULL;
58
59 // Cache current interface number that will be used in
60 // WinUsb_Xxx calls performed on this interface.
61 if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))
62 return false;
63
64 // Cache interface properties
65 unsigned long bytes_written;
66
67 // Cache USB device descriptor
68 if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
69 reinterpret_cast<PUCHAR>(&usb_device_descriptor_),
70 sizeof(usb_device_descriptor_), &bytes_written)) {
71 return false;
72 }
73
74 // Cache USB configuration descriptor
75 if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE,
76 0, 0,
77 reinterpret_cast<PUCHAR>(&usb_config_descriptor_),
78 sizeof(usb_config_descriptor_), &bytes_written)) {
79 return false;
80 }
81
82 // Cache USB interface descriptor
83 if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(),
84 &usb_interface_descriptor_)) {
85 return false;
86 }
87
88 // Save indexes and IDs for bulk read / write endpoints. We will use them to
89 // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
90 // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
91 for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
92 endpoint++) {
93 // Get endpoint information
94 WINUSB_PIPE_INFORMATION pipe_info;
95 if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint,
96 &pipe_info)) {
97 return false;
98 }
99
100 if (UsbdPipeTypeBulk == pipe_info.PipeType) {
101 // This is a bulk endpoint. Cache its index and ID.
102 if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) {
103 // Use this endpoint as default bulk read endpoint
104 ATLASSERT(0xFF == def_read_endpoint_);
105 def_read_endpoint_ = endpoint;
106 read_endpoint_id_ = pipe_info.PipeId;
107 } else {
108 // Use this endpoint as default bulk write endpoint
109 ATLASSERT(0xFF == def_write_endpoint_);
110 def_write_endpoint_ = endpoint;
111 write_endpoint_id_ = pipe_info.PipeId;
112 }
113 }
114 }
115
116 return AdbObjectHandle::CreateHandle();
117}
118
119bool AdbInterfaceObject::CloseHandle() {
120 if (NULL != winusb_handle_) {
121 WinUsb_Free(winusb_handle_);
122 winusb_handle_ = NULL;
123 }
124 if (INVALID_HANDLE_VALUE != usb_device_handle_) {
125 ::CloseHandle(usb_device_handle_);
126 usb_device_handle_ = INVALID_HANDLE_VALUE;
127 }
128
129 return AdbObjectHandle::CloseHandle();
130}
131
132bool AdbInterfaceObject::GetInterfaceName(void* buffer,
133 unsigned long* buffer_char_size,
134 bool ansi) {
135 if (NULL == buffer_char_size) {
136 SetLastError(ERROR_INVALID_PARAMETER);
137 return false;
138 }
139
140 // Lets see if buffer is big enough
141 ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);
142 if ((NULL == buffer) || (*buffer_char_size < name_len)) {
143 *buffer_char_size = name_len;
144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
145 return false;
146 }
147
148 if (!ansi) {
149 // If user asked for wide char name just return it
150 wcscpy(reinterpret_cast<wchar_t*>(buffer), interface_name().c_str());
151 return true;
152 }
153
154 // We need to convert name from wide char to ansi string
155 int res = WideCharToMultiByte(CP_ACP,
156 0,
157 interface_name().c_str(),
158 static_cast<int>(name_len),
159 reinterpret_cast<PSTR>(buffer),
160 static_cast<int>(*buffer_char_size),
161 NULL,
162 NULL);
163 return (res != 0);
164}
165
166bool AdbInterfaceObject::GetSerialNumber(void* buffer,
167 unsigned long* buffer_char_size,
168 bool ansi) {
169 if (!IsOpened()) {
170 SetLastError(ERROR_INVALID_HANDLE);
171 return false;
172 }
173
174 if (NULL == buffer_char_size) {
175 SetLastError(ERROR_INVALID_PARAMETER);
176 return false;
177 }
178
179 // Calculate serial number string size. Note that WinUsb_GetDescriptor
180 // API will not return number of bytes needed to store serial number
181 // string. So we will have to start with a reasonably large preallocated
182 // buffer and then loop through WinUsb_GetDescriptor calls, doubling up
183 // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned.
184 union {
185 // Preallocate reasonably sized buffer on the stack.
186 char small_buffer[64];
187 USB_STRING_DESCRIPTOR initial_ser_num;
188 };
189 USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num;
190 // Buffer byte size
191 unsigned long ser_num_size = sizeof(small_buffer);
192 // After successful call to WinUsb_GetDescriptor will contain serial
193 // number descriptor size.
194 unsigned long bytes_written;
195 while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE,
196 usb_device_descriptor_.iSerialNumber,
197 0x0409, // English (US)
198 reinterpret_cast<PUCHAR>(ser_num),
199 ser_num_size, &bytes_written)) {
200 // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here.
201 if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
202 if (ser_num != &initial_ser_num)
203 delete[] reinterpret_cast<char*>(ser_num);
204 return false;
205 }
206
207 // Double up buffer size and reallocate string buffer
208 ser_num_size *= 2;
209 if (ser_num != &initial_ser_num)
210 delete[] reinterpret_cast<char*>(ser_num);
211 try {
212 ser_num =
213 reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]);
214 } catch (...) {
215 SetLastError(ERROR_OUTOFMEMORY);
216 return false;
217 }
218 }
219
220 // Serial number string length
221 unsigned long str_len = (ser_num->bLength -
222 FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) /
223 sizeof(wchar_t);
224
225 // Lets see if requested buffer is big enough to fit the string
226 if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) {
227 // Requested buffer is too small.
228 if (ser_num != &initial_ser_num)
229 delete[] reinterpret_cast<char*>(ser_num);
230 *buffer_char_size = str_len + 1;
231 SetLastError(ERROR_INSUFFICIENT_BUFFER);
232 return false;
233 }
234
235 bool ret = true;
236 if (ansi) {
237 // We need to convert name from wide char to ansi string
238 if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString,
239 static_cast<int>(str_len),
240 reinterpret_cast<PSTR>(buffer),
241 static_cast<int>(*buffer_char_size),
242 NULL, NULL)) {
243 // Zero-terminate output string.
244 reinterpret_cast<char*>(buffer)[str_len] = '\0';
245 } else {
246 ret = false;
247 }
248 } else {
249 // For wide char output just copy string buffer,
250 // and zero-terminate output string.
251 CopyMemory(buffer, ser_num->bString, bytes_written);
252 reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0';
253 }
254
255 if (ser_num != &initial_ser_num)
256 delete[] reinterpret_cast<char*>(ser_num);
257
258 return ret;
259}
260
261bool AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) {
262 if (!IsOpened()) {
263 SetLastError(ERROR_INVALID_HANDLE);
264 return false;
265 }
266
267 if (NULL == desc) {
268 SetLastError(ERROR_INVALID_PARAMETER);
269 return false;
270 }
271
272 CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));
273
274 return true;
275}
276
277bool AdbInterfaceObject::GetUsbConfigurationDescriptor(
278 USB_CONFIGURATION_DESCRIPTOR* desc) {
279 if (!IsOpened()) {
280 SetLastError(ERROR_INVALID_HANDLE);
281 return false;
282 }
283
284 if (NULL == desc) {
285 SetLastError(ERROR_INVALID_PARAMETER);
286 return false;
287 }
288
289 CopyMemory(desc, usb_config_descriptor(),
290 sizeof(USB_CONFIGURATION_DESCRIPTOR));
291
292 return true;
293}
294
295bool AdbInterfaceObject::GetUsbInterfaceDescriptor(
296 USB_INTERFACE_DESCRIPTOR* desc) {
297 if (!IsOpened()) {
298 SetLastError(ERROR_INVALID_HANDLE);
299 return false;
300 }
301
302 if (NULL == desc) {
303 SetLastError(ERROR_INVALID_PARAMETER);
304 return false;
305 }
306
307 CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));
308
309 return true;
310}
311
312bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,
313 AdbEndpointInformation* info) {
314 if (!IsOpened()) {
315 SetLastError(ERROR_INVALID_HANDLE);
316 return false;
317 }
318
319 if (NULL == info) {
320 SetLastError(ERROR_INVALID_PARAMETER);
321 return false;
322 }
323
324 // Get actual endpoint index for predefined read / write endpoints.
325 if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
326 endpoint_index = def_read_endpoint_;
327 } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
328 endpoint_index = def_write_endpoint_;
329 }
330
331 // Query endpoint information
332 WINUSB_PIPE_INFORMATION pipe_info;
333 if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,
334 &pipe_info)) {
335 return false;
336 }
337
338 // Save endpoint information into output.
339 info->max_packet_size = pipe_info.MaximumPacketSize;
340 info->max_transfer_size = 0xFFFFFFFF;
341 info->endpoint_address = pipe_info.PipeId;
342 info->polling_interval = pipe_info.Interval;
343 info->setting_index = interface_number();
344 switch (pipe_info.PipeType) {
345 case UsbdPipeTypeControl:
346 info->endpoint_type = AdbEndpointTypeControl;
347 break;
348
349 case UsbdPipeTypeIsochronous:
350 info->endpoint_type = AdbEndpointTypeIsochronous;
351 break;
352
353 case UsbdPipeTypeBulk:
354 info->endpoint_type = AdbEndpointTypeBulk;
355 break;
356
357 case UsbdPipeTypeInterrupt:
358 info->endpoint_type = AdbEndpointTypeInterrupt;
359 break;
360
361 default:
362 info->endpoint_type = AdbEndpointTypeInvalid;
363 break;
364 }
365
366 return true;
367}
368
369ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
370 UCHAR endpoint_index,
371 AdbOpenAccessType access_type,
372 AdbOpenSharingMode sharing_mode) {
373 // Convert index into id
374 UCHAR endpoint_id;
375
376 if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
377 (def_read_endpoint_ == endpoint_index)) {
378 endpoint_id = read_endpoint_id_;
379 endpoint_index = def_read_endpoint_;
380 } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
381 (def_write_endpoint_ == endpoint_index)) {
382 endpoint_id = write_endpoint_id_;
383 endpoint_index = def_write_endpoint_;
384 } else {
385 SetLastError(ERROR_INVALID_PARAMETER);
386 return false;
387 }
388
389 return OpenEndpoint(endpoint_id, endpoint_index);
390}
391
392ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
393 UCHAR endpoint_index) {
394 if (!IsOpened()) {
395 SetLastError(ERROR_INVALID_HANDLE);
396 return false;
397 }
398
399 AdbEndpointObject* adb_endpoint = NULL;
400
401 try {
402 adb_endpoint = new AdbEndpointObject(this, endpoint_id, endpoint_index);
403 } catch (...) {
404 SetLastError(ERROR_OUTOFMEMORY);
405 return NULL;
406 }
407
408 ADBAPIHANDLE ret = adb_endpoint->CreateHandle();
409
410 adb_endpoint->Release();
411
412 return ret;
413}