238 lines
7.6 KiB
C++
Executable File
238 lines
7.6 KiB
C++
Executable File
/*
|
|
* Copyright (C) 2009 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/** \file
|
|
This file consists of implementation of class AdbLegacyEndpointObject that
|
|
encapsulates a handle opened to an endpoint on our device controlled by
|
|
a custom (legacy) USB driver.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "adb_api_legacy.h"
|
|
#include "adb_legacy_endpoint_object.h"
|
|
#include "adb_legacy_io_completion.h"
|
|
#include "adb_helper_routines.h"
|
|
|
|
AdbLegacyEndpointObject::AdbLegacyEndpointObject(
|
|
AdbLegacyInterfaceObject* parent_interf,
|
|
UCHAR endpoint_id,
|
|
UCHAR endpoint_index)
|
|
: AdbEndpointObject(parent_interf, endpoint_id, endpoint_index),
|
|
usb_handle_(INVALID_HANDLE_VALUE) {
|
|
}
|
|
|
|
AdbLegacyEndpointObject::~AdbLegacyEndpointObject() {
|
|
if (INVALID_HANDLE_VALUE != usb_handle_) {
|
|
::CloseHandle(usb_handle_);
|
|
}
|
|
}
|
|
|
|
ADBAPIHANDLE AdbLegacyEndpointObject::CommonAsyncReadWrite(
|
|
bool is_read,
|
|
void* buffer,
|
|
ULONG bytes_to_transfer,
|
|
ULONG* bytes_transferred,
|
|
HANDLE event_handle,
|
|
ULONG time_out) {
|
|
if (NULL != bytes_transferred) {
|
|
*bytes_transferred = 0;
|
|
}
|
|
|
|
if (!IsOpened()) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return false;
|
|
}
|
|
|
|
bool is_ioctl_write = is_read ? false : (0 != time_out);
|
|
|
|
// Create completion i/o object
|
|
AdbLegacyIOCompletion* adb_io_completion = NULL;
|
|
|
|
try {
|
|
adb_io_completion = new AdbLegacyIOCompletion(this,
|
|
bytes_to_transfer,
|
|
event_handle,
|
|
is_ioctl_write);
|
|
} catch (... ) {
|
|
// We don't expect exceptions other than OOM thrown here.
|
|
SetLastError(ERROR_OUTOFMEMORY);
|
|
return NULL;
|
|
}
|
|
|
|
// Create a handle for it
|
|
ADBAPIHANDLE ret = adb_io_completion->CreateHandle();
|
|
ULONG transferred = 0;
|
|
if (NULL != ret) {
|
|
BOOL res = TRUE;
|
|
if (0 == time_out) {
|
|
// Go the read / write file way
|
|
res = is_read ? ReadFile(usb_handle(),
|
|
buffer,
|
|
bytes_to_transfer,
|
|
&transferred,
|
|
adb_io_completion->overlapped()) :
|
|
WriteFile(usb_handle(),
|
|
buffer,
|
|
bytes_to_transfer,
|
|
&transferred,
|
|
adb_io_completion->overlapped());
|
|
} else {
|
|
// Go IOCTL way
|
|
AdbBulkTransfer transfer_param;
|
|
transfer_param.time_out = time_out;
|
|
transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
|
|
transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
|
|
|
|
res = DeviceIoControl(usb_handle(),
|
|
is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
|
|
&transfer_param, sizeof(transfer_param),
|
|
is_read ? buffer : adb_io_completion->transferred_bytes_ptr(),
|
|
is_read ? bytes_to_transfer : sizeof(ULONG),
|
|
&transferred,
|
|
adb_io_completion->overlapped());
|
|
}
|
|
|
|
if (NULL != bytes_transferred) {
|
|
*bytes_transferred = transferred;
|
|
}
|
|
|
|
ULONG error = GetLastError();
|
|
if (!res && (ERROR_IO_PENDING != error)) {
|
|
// I/O failed immediatelly. We need to close i/o completion object
|
|
// before we return NULL to the caller.
|
|
adb_io_completion->CloseHandle();
|
|
ret = NULL;
|
|
SetLastError(error);
|
|
}
|
|
}
|
|
|
|
// Offseting 'new'
|
|
adb_io_completion->Release();
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool AdbLegacyEndpointObject::CommonSyncReadWrite(bool is_read,
|
|
void* buffer,
|
|
ULONG bytes_to_transfer,
|
|
ULONG* bytes_transferred,
|
|
ULONG time_out) {
|
|
if (NULL != bytes_transferred) {
|
|
*bytes_transferred = 0;
|
|
}
|
|
|
|
if (!IsOpened()) {
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
return false;
|
|
}
|
|
|
|
bool is_ioctl_write = is_read ? false : (0 != time_out);
|
|
|
|
// This is synchronous I/O. Since we always open I/O items for
|
|
// overlapped I/O we're obligated to always provide OVERLAPPED
|
|
// structure to read / write routines. Prepare it now.
|
|
OVERLAPPED overlapped;
|
|
ZeroMemory(&overlapped, sizeof(overlapped));
|
|
|
|
BOOL ret = TRUE;
|
|
ULONG ioctl_write_transferred = 0;
|
|
if (0 == time_out) {
|
|
// Go the read / write file way
|
|
ret = is_read ?
|
|
ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) :
|
|
WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped);
|
|
} else {
|
|
// Go IOCTL way
|
|
AdbBulkTransfer transfer_param;
|
|
transfer_param.time_out = time_out;
|
|
transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
|
|
transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
|
|
|
|
ULONG tmp;
|
|
ret = DeviceIoControl(usb_handle(),
|
|
is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
|
|
&transfer_param, sizeof(transfer_param),
|
|
is_read ? buffer : &ioctl_write_transferred,
|
|
is_read ? bytes_to_transfer : sizeof(ULONG),
|
|
&tmp,
|
|
&overlapped);
|
|
}
|
|
|
|
// Lets see the result
|
|
if (!ret && (ERROR_IO_PENDING != GetLastError())) {
|
|
// I/O failed.
|
|
return false;
|
|
}
|
|
|
|
// Lets wait till I/O completes
|
|
ULONG transferred = 0;
|
|
ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE);
|
|
if (ret && (NULL != bytes_transferred)) {
|
|
*bytes_transferred = is_ioctl_write ? ioctl_write_transferred :
|
|
transferred;
|
|
}
|
|
|
|
return ret ? true : false;
|
|
}
|
|
|
|
ADBAPIHANDLE AdbLegacyEndpointObject::CreateHandle(
|
|
const wchar_t* item_path,
|
|
AdbOpenAccessType access_type,
|
|
AdbOpenSharingMode share_mode) {
|
|
// Convert access / share parameters into CreateFile - compatible
|
|
ULONG desired_access;
|
|
ULONG desired_sharing;
|
|
|
|
if (!GetSDKComplientParam(access_type, share_mode,
|
|
&desired_access, &desired_sharing)) {
|
|
return NULL;
|
|
}
|
|
|
|
// Open USB handle
|
|
usb_handle_ = CreateFile(item_path,
|
|
desired_access,
|
|
share_mode,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_FLAG_OVERLAPPED, // Always overlapped!
|
|
NULL);
|
|
if (INVALID_HANDLE_VALUE == usb_handle_) {
|
|
return NULL;
|
|
}
|
|
|
|
// Create ADB handle
|
|
ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle();
|
|
|
|
if (NULL == ret) {
|
|
// If creation of ADB handle failed we have to close USB handle too.
|
|
ULONG error = GetLastError();
|
|
::CloseHandle(usb_handle());
|
|
usb_handle_ = INVALID_HANDLE_VALUE;
|
|
SetLastError(error);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool AdbLegacyEndpointObject::CloseHandle() {
|
|
if (INVALID_HANDLE_VALUE != usb_handle_) {
|
|
::CloseHandle(usb_handle_);
|
|
usb_handle_ = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
return AdbEndpointObject::CloseHandle();
|
|
}
|