summaryrefslogtreecommitdiff
path: root/host/windows/usb/api/adb_io_object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/windows/usb/api/adb_io_object.cpp')
-rw-r--r--host/windows/usb/api/adb_io_object.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/host/windows/usb/api/adb_io_object.cpp b/host/windows/usb/api/adb_io_object.cpp
new file mode 100644
index 000000000..732dc22b6
--- /dev/null
+++ b/host/windows/usb/api/adb_io_object.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2006 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 AdbIOObject that encapsulates
+ an item on our device that is opened for read / write / IOCTL I/O.
+*/
+
+#include "stdafx.h"
+#include "adb_io_object.h"
+#include "adb_io_completion.h"
+#include "adb_helper_routines.h"
+
+AdbIOObject::AdbIOObject(AdbInterfaceObject* parent_interf,
+ AdbObjectType obj_type)
+ : AdbObjectHandle(obj_type),
+ usb_handle_(INVALID_HANDLE_VALUE),
+ parent_interface_(parent_interf) {
+ ATLASSERT(NULL != parent_interf);
+ parent_interf->AddRef();
+}
+
+AdbIOObject::~AdbIOObject() {
+ if (INVALID_HANDLE_VALUE != usb_handle_)
+ ::CloseHandle(usb_handle_);
+ parent_interface_->Release();
+}
+
+ADBAPIHANDLE AdbIOObject::CreateHandle(const wchar_t* item_path,
+ AdbOpenAccessType access_type,
+ AdbOpenSharingMode share_mode) {
+ // Make sure that we don't have USB handle here
+ if (IsUsbOpened()) {
+ SetLastError(ERROR_GEN_FAILURE);
+ return NULL;
+ }
+
+ // 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 AdbIOObject::CloseHandle() {
+ // Lets close USB item first
+ if (IsUsbOpened()) {
+ ::CloseHandle(usb_handle());
+ usb_handle_ = INVALID_HANDLE_VALUE;
+ }
+
+ return AdbObjectHandle::CloseHandle();
+}
+
+ADBAPIHANDLE AdbIOObject::AsyncRead(void* buffer,
+ ULONG bytes_to_read,
+ ULONG* bytes_read,
+ HANDLE event_handle,
+ ULONG time_out) {
+ return CommonAsyncReadWrite(true,
+ buffer,
+ bytes_to_read,
+ bytes_read,
+ event_handle,
+ time_out);
+}
+
+ADBAPIHANDLE AdbIOObject::AsyncWrite(void* buffer,
+ ULONG bytes_to_write,
+ ULONG* bytes_written,
+ HANDLE event_handle,
+ ULONG time_out) {
+ return CommonAsyncReadWrite(false,
+ buffer,
+ bytes_to_write,
+ bytes_written,
+ event_handle,
+ time_out);
+}
+
+bool AdbIOObject::SyncRead(void* buffer,
+ ULONG bytes_to_read,
+ ULONG* bytes_read,
+ ULONG time_out) {
+ return CommonSyncReadWrite(true,
+ buffer,
+ bytes_to_read,
+ bytes_read,
+ time_out);
+}
+
+bool AdbIOObject::SyncWrite(void* buffer,
+ ULONG bytes_to_write,
+ ULONG* bytes_written,
+ ULONG time_out) {
+ return CommonSyncReadWrite(false,
+ buffer,
+ bytes_to_write,
+ bytes_written,
+ time_out);
+}
+
+ADBAPIHANDLE AdbIOObject::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() || !IsUsbOpened()) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ bool is_ioctl_write = is_read ? false : (0 != time_out);
+
+ // Create completion i/o object
+ AdbIOCompletion* adb_io_completion = NULL;
+
+ try {
+ adb_io_completion = new AdbIOCompletion(this,
+ is_ioctl_write,
+ bytes_to_transfer,
+ event_handle);
+ } catch (... ) {
+ 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 AdbIOObject::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() || !IsUsbOpened()) {
+ 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;
+}