diff options
author | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 00:41:57 +0900 |
---|---|---|
committer | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 00:41:57 +0900 |
commit | aa44aabb66da71d4380b74481f609f6daac2c269 (patch) | |
tree | d0ffbd64e7371bded3c7ffd472464774f908e941 /src/sdbwinusbapi | |
parent | 041e6080ec2c7e6db643943434e7ddff49ffb68a (diff) | |
download | sdb-tizen_2.0.tar.gz sdb-tizen_2.0.tar.bz2 sdb-tizen_2.0.zip |
Tizen 2.0 Releasesubmit/tizen_2.0/20130215.192027tizen_2.0
Diffstat (limited to 'src/sdbwinusbapi')
-rw-r--r-- | src/sdbwinusbapi/BUILDME.TXT | 7 | ||||
-rw-r--r-- | src/sdbwinusbapi/MAKEFILE | 22 | ||||
-rw-r--r-- | src/sdbwinusbapi/Resource.h | 34 | ||||
-rw-r--r-- | src/sdbwinusbapi/SOURCES | 91 | ||||
-rw-r--r-- | src/sdbwinusbapi/SdbWinUsbApi.cpp | 62 | ||||
-rw-r--r-- | src/sdbwinusbapi/SdbWinUsbApi.def | 5 | ||||
-rw-r--r-- | src/sdbwinusbapi/SdbWinUsbApi.rc | 111 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_endpoint_object.cpp | 169 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_endpoint_object.h | 155 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_interface.cpp | 340 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_interface.h | 205 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_io_completion.cpp | 98 | ||||
-rw-r--r-- | src/sdbwinusbapi/sdb_winusb_io_completion.h | 118 | ||||
-rw-r--r-- | src/sdbwinusbapi/stdafx.cpp | 21 | ||||
-rw-r--r-- | src/sdbwinusbapi/stdafx.h | 78 |
15 files changed, 1516 insertions, 0 deletions
diff --git a/src/sdbwinusbapi/BUILDME.TXT b/src/sdbwinusbapi/BUILDME.TXT new file mode 100644 index 0000000..b130472 --- /dev/null +++ b/src/sdbwinusbapi/BUILDME.TXT @@ -0,0 +1,7 @@ +In order to build SdbWinUsbApi.dll you will need to install Windows Driver Kit, +which can be obtained from Microsoft. Assuming that WDK is installed, you +need to set one of the WDK's build environments, "cd" back into this directory, +and execute "build -cbeEIFZ" to clean and rebuild this project, or you can +execute "build -befEIF" to do a minimal build. +Note that you need to build SdbWinApi.dll (..\api) before you build +SdbWinUsbApi.dll, as it depends on SdbWinApi.lib library. diff --git a/src/sdbwinusbapi/MAKEFILE b/src/sdbwinusbapi/MAKEFILE new file mode 100644 index 0000000..87a1295 --- /dev/null +++ b/src/sdbwinusbapi/MAKEFILE @@ -0,0 +1,22 @@ +# +# 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. +# + +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/src/sdbwinusbapi/Resource.h b/src/sdbwinusbapi/Resource.h new file mode 100644 index 0000000..7d883c7 --- /dev/null +++ b/src/sdbwinusbapi/Resource.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by SdbWinApi.rc +// + +#define IDS_PROJNAME 100 +#define IDR_SDBWINAPI 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 201 +#define _APS_NEXT_COMMAND_VALUE 32768 +#define _APS_NEXT_CONTROL_VALUE 201 +#define _APS_NEXT_SYMED_VALUE 102 +#endif +#endif diff --git a/src/sdbwinusbapi/SOURCES b/src/sdbwinusbapi/SOURCES new file mode 100644 index 0000000..90be2c1 --- /dev/null +++ b/src/sdbwinusbapi/SOURCES @@ -0,0 +1,91 @@ +# +# 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. +# + +TARGETNAME = SdbWinUsbApi +TARGETPATH = obj +TARGETTYPE = DYNLINK + +UMTYPE = windows +DLLDEF = SdbWinUsbApi.def + +# Use statically linked atl libraries: +# - atls.lib for free build +# - atlsd.lib for checked build +USE_STATIC_ATL = 1 +# Use ATL v. 7.1 +ATL_VER = 71 +# Use STL v. 6.0 +USE_STL = 1 +STL_VER = 60 +# Use multithreaded libraries +USE_LIBCMT = 1 + +# Include directories +INCLUDES = $(DDK_INC_PATH); \ + $(SDK_INC_PATH); \ + $(CRT_INC_PATH); \ + $(SDK_INC_PATH)\crt; \ + $(CRT_INC_PATH)\atl71; \ + $(SDK_INC_PATH)\crt\stl60 + +# Common target libraries +TARGETLIBS = $(SDK_LIB_PATH)\ole32.lib \ + $(SDK_LIB_PATH)\Advapi32.lib \ + $(SDK_LIB_PATH)\Kernel32.lib \ + $(SDK_LIB_PATH)\User32.lib \ + $(SDK_LIB_PATH)\oleaut32.lib \ + $(SDK_LIB_PATH)\wbemuuid.lib \ + $(SDK_LIB_PATH)\uuid.lib \ + $(SDK_LIB_PATH)\setupapi.lib \ + $(SDK_LIB_PATH)\usbd.lib \ + $(SDK_LIB_PATH)\winusb.lib \ + ..\sdbwinapi\obj$(BUILD_ALT_DIR)\i386\SdbWinApi.lib + +!IF "$(DDKBUILDENV)" == "fre" +# Libraries for release (free) builds +TARGETLIBS = $(TARGETLIBS) $(ATL_LIB_PATH)\atls.lib +!ELSE +# Libraries for debug (checked) builds +TARGETLIBS = $(TARGETLIBS) $(ATL_LIB_PATH)\atlsd.lib +!ENDIF + +# Common C defines +C_DEFINES= $(C_DEFINES) -DSDBWINUSB_EXPORTS -D_UNICODE \ + -DUNICODE -DWIN32 -D_WINDOWS -D_USRDLL -D_WINDLL + +!IF "$(DDKBUILDENV)" == "fre" +# C defines for release (free) builds +C_DEFINES = $(C_DEFINES) -DNDEBUG +!ELSE +# C defines for debug (checked) builds +C_DEFINES = $(C_DEFINES) -D_DEBUG +!ENDIF + +# Turn on all warnings, and treat warnings as errors +MSC_WARNING_LEVEL = /W4 /Wp64 /WX +# Common C defines +USER_C_FLAGS = $(USER_C_FLAGS) /FD /EHsc /wd4100 /wd4200 /wd4702 /nologo +# Set precompiled header information +PRECOMPILED_CXX = 1 +PRECOMPILED_INCLUDE = stdafx.h +PRECOMPILED_SOURCEFILE = stdafx.cpp + +# Define source files for SdbWinUsbApi.dll +SOURCES = sdb_winusb_endpoint_object.cpp \ + sdb_winusb_interface.cpp \ + sdb_winusb_io_completion.cpp \ + SdbWinUsbApi.cpp \ + SdbWinUsbApi.rc diff --git a/src/sdbwinusbapi/SdbWinUsbApi.cpp b/src/sdbwinusbapi/SdbWinUsbApi.cpp new file mode 100644 index 0000000..e656e94 --- /dev/null +++ b/src/sdbwinusbapi/SdbWinUsbApi.cpp @@ -0,0 +1,62 @@ +/* + * 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. + */ + +// SdbWinUsbApi.cpp : Implementation of DLL Exports. + +#include "stdafx.h" +#include "sdb_winusb_interface.h" + +class CSdbWinApiModule : public CAtlDllModuleT< CSdbWinApiModule > { +public: +}; + +CSdbWinApiModule _AtlModule; + +// DLL Entry Point +extern "C" BOOL WINAPI DllMain(HINSTANCE instance, + DWORD reason, + LPVOID reserved) { + return _AtlModule.DllMain(reason, reserved); +} + +/** \brief Instantiates interface instance that uses WinUsb API to communicate + with USB driver. + + This is the only exported routine from this DLL. This routine instantiates an + object of SdbWinUsbInterfaceObject on request from SdbWinApi.dll when it is + detected that underlying USB driver is WinUsb.sys. + @param[in] interface_name Name of the interface. + @return SdbInterfaceObject - casted instance of SdbWinUsbInterfaceObject + object on success, or NULL on failure with GetLastError providing + information on an error that occurred. +*/ +extern "C" __declspec(dllexport) +SdbInterfaceObject* __cdecl InstantiateSdbWinUsbInterface( + const wchar_t* interface_name) { + // Validate parameter. + if (NULL == interface_name) { + return NULL; + } + + // Instantiate requested object. + try { + return new SdbWinUsbInterfaceObject(interface_name); + } catch (...) { + // We expect only OOM exceptions here. + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } +} diff --git a/src/sdbwinusbapi/SdbWinUsbApi.def b/src/sdbwinusbapi/SdbWinUsbApi.def new file mode 100644 index 0000000..06aac0b --- /dev/null +++ b/src/sdbwinusbapi/SdbWinUsbApi.def @@ -0,0 +1,5 @@ +; SdbWinUsbApi.def : Declares the module parameters. + +LIBRARY "SdbWinUsbApi.DLL" + +EXPORTS diff --git a/src/sdbwinusbapi/SdbWinUsbApi.rc b/src/sdbwinusbapi/SdbWinUsbApi.rc new file mode 100644 index 0000000..d19be52 --- /dev/null +++ b/src/sdbwinusbapi/SdbWinUsbApi.rc @@ -0,0 +1,111 @@ +/* + * 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. + */ + +//Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,0,0,0 + PRODUCTVERSION 2,0,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Google, inc" + VALUE "FileDescription", "Android SDB API (WinUsb)" + VALUE "FileVersion", "2.0.0.0" + VALUE "LegalCopyright", "Copyright (C) 2006 The Android Open Source Project" + VALUE "InternalName", "SdbWinUsbApi.dll" + VALUE "OriginalFilename", "SdbWinUsbApi.dll" + VALUE "ProductName", "Android SDK" + VALUE "ProductVersion", "2.0.0.0" + VALUE "OLESelfRegister", "" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END + +#endif // !_MAC + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_PROJNAME "SdbWinUsbApi" +END + +//////////////////////////////////////////////////////////////////////////// + + +#endif + +#ifndef APSTUDIO_INVOKED +#endif // not APSTUDIO_INVOKED diff --git a/src/sdbwinusbapi/sdb_winusb_endpoint_object.cpp b/src/sdbwinusbapi/sdb_winusb_endpoint_object.cpp new file mode 100644 index 0000000..8b5e891 --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_endpoint_object.cpp @@ -0,0 +1,169 @@ +/* + * 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 SdbWinUsbEndpointObject that + encapsulates a handle opened to a WinUsb endpoint on our device. +*/ + +#include "stdafx.h" +#include "sdb_winusb_endpoint_object.h" +#include "sdb_winusb_io_completion.h" + +SdbWinUsbEndpointObject::SdbWinUsbEndpointObject( + SdbWinUsbInterfaceObject* parent_interf, + UCHAR endpoint_id, + UCHAR endpoint_index) + : SdbEndpointObject(parent_interf, endpoint_id, endpoint_index) { +} + +SdbWinUsbEndpointObject::~SdbWinUsbEndpointObject() { +} + +LONG SdbWinUsbEndpointObject::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + +SDBAPIHANDLE SdbWinUsbEndpointObject::CommonAsyncReadWrite( + bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + HANDLE event_handle, + ULONG time_out) { + if (!SetTimeout(time_out)) + return false; + + // Create completion i/o object + SdbIOCompletion* sdb_io_completion = NULL; + + try { + sdb_io_completion = new SdbWinUsbIOCompletion(this, + bytes_to_transfer, + event_handle); + } catch (... ) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + // Create a handle for it + SDBAPIHANDLE ret = sdb_io_completion->CreateHandle(); + ULONG transferred = 0; + if (NULL != ret) { + BOOL res = TRUE; + // Go the read / write file way + res = is_read ? + WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast<PUCHAR>(buffer), + bytes_to_transfer, + &transferred, + sdb_io_completion->overlapped()) : + WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast<PUCHAR>(buffer), + bytes_to_transfer, + &transferred, + sdb_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. + sdb_io_completion->CloseHandle(); + ret = NULL; + SetLastError(error); + } + } + + // Offseting 'new' + sdb_io_completion->Release(); + + return ret; +} + +bool SdbWinUsbEndpointObject::CommonSyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + ULONG time_out) { + if (!SetTimeout(time_out)) + return false; + + // 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)); + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + BOOL ret = TRUE; + ULONG transferred = 0; + // Go the read / write file way + ret = is_read ? + WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast<PUCHAR>(buffer), + bytes_to_transfer, + &transferred, + &overlapped) : + WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast<PUCHAR>(buffer), + bytes_to_transfer, + &transferred, + &overlapped); + + // Lets see the result + if (!ret && (ERROR_IO_PENDING != GetLastError())) { + // I/O failed. + if (NULL != overlapped.hEvent) + ::CloseHandle(overlapped.hEvent); + return false; + } + + // Lets wait till I/O completes + ret = WinUsb_GetOverlappedResult(parent_winusb_interface()->winusb_handle(), &overlapped, + &transferred, TRUE); + if (ret && (NULL != bytes_transferred)) { + *bytes_transferred = transferred; + } + + if (NULL != overlapped.hEvent) + ::CloseHandle(overlapped.hEvent); + + return ret ? true : false; +} + +bool SdbWinUsbEndpointObject::SetTimeout(ULONG timeout) { + if (!WinUsb_SetPipePolicy(parent_winusb_interface()->winusb_handle(), + endpoint_id(), PIPE_TRANSFER_TIMEOUT, + sizeof(ULONG), &timeout)) { + return false; + } + + return true; +} diff --git a/src/sdbwinusbapi/sdb_winusb_endpoint_object.h b/src/sdbwinusbapi/sdb_winusb_endpoint_object.h new file mode 100644 index 0000000..bd7b38b --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_endpoint_object.h @@ -0,0 +1,155 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_SDB_WINUSB_ENDPOINT_OBJECT_H__ +#define ANDROID_USB_API_SDB_WINUSB_ENDPOINT_OBJECT_H__ +/** \file + This file consists of declaration of class SdbWinUsbEndpointObject that + encapsulates a handle opened to a WinUsb endpoint on our device. +*/ + +#include "..\sdbwinapi\sdb_endpoint_object.h" +#include "sdb_winusb_interface.h" + +/** Class SdbWinUsbEndpointObject encapsulates a handle opened to an endpoint on + our device. +*/ +class SdbWinUsbEndpointObject : public SdbEndpointObject { + public: + /** \brief Constructs the object + + @param[in] interface Parent WinUsb interface for this object. + @param[in] endpoint_id Endpoint ID (endpoint address) on the device. + @param[in] endpoint_index Zero-based endpoint index in the interface's + array of endpoints. + */ + SdbWinUsbEndpointObject(SdbWinUsbInterfaceObject* parent_interf, + UCHAR endpoint_id, + UCHAR endpoint_index); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~SdbWinUsbEndpointObject(); + + // + // Virtual overrides + // + + public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of SdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of SdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + + // + // Abstract overrides + // + + protected: + /** \brief Common code for async read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] event_handle Event handle that should be signaled when async I/O + completes. Can be NULL. If it's not NULL this handle will be used to + initialize OVERLAPPED structure for this I/O. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return A handle to IO completion object or NULL on failure. If NULL is + returned GetLastError() provides extended error information. + */ + virtual SDBAPIHANDLE CommonAsyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + HANDLE event_handle, + ULONG time_out); + + /** \brief Common code for sync read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool CommonSyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + ULONG time_out); + + // + // Operations + // + + protected: + /** \brief Sets read / write operation timeout. + + @param[in] timeout Timeout value in milliseconds to use for current read + or write operation. Zero value passed in this parameters indicate + not timeout at all. Note that timeout that is set with this method is + global per endpoint (pipe). I.e. once set, it will be used against + all read / write operations performed on this endpoint, untill + another call to this method modifies it. This is a WinUsb design + flaw. Microsoft is aware of this and (hopefuly) future versions of + WinUsb framework will accept a timeout parameter in WinUsb_Read/Write + routines. For the purposes of SDB this flaw doesn't apperar to be an + issue, since we use single-threaded synchronous read / writes, so + there is no conflict in setting per-endpoint timeouts. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool SetTimeout(ULONG timeout); + + public: + /// Gets parent WinUsb interface + SdbWinUsbInterfaceObject* parent_winusb_interface() const { + return reinterpret_cast<SdbWinUsbInterfaceObject*>(parent_interface()); + } + + /// Gets parent interface WinUsb handle + WINUSB_INTERFACE_HANDLE winusb_handle() const { + return parent_winusb_interface()->winusb_handle(); + } +}; + +#endif // ANDROID_USB_API_SDB_WINUSB_ENDPOINT_OBJECT_H__ diff --git a/src/sdbwinusbapi/sdb_winusb_interface.cpp b/src/sdbwinusbapi/sdb_winusb_interface.cpp new file mode 100644 index 0000000..3fcdce7 --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_interface.cpp @@ -0,0 +1,340 @@ +/* + * 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 SdbWinUsbInterfaceObject + that encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ + +#include "stdafx.h" +#include "sdb_winusb_interface.h" +#include "sdb_winusb_endpoint_object.h" + +SdbWinUsbInterfaceObject::SdbWinUsbInterfaceObject(const wchar_t* interf_name) + : SdbInterfaceObject(interf_name), + usb_device_handle_(INVALID_HANDLE_VALUE), + winusb_handle_(NULL), + interface_number_(0xFF), + def_read_endpoint_(0xFF), + read_endpoint_id_(0xFF), + def_write_endpoint_(0xFF), + write_endpoint_id_(0xFF) { +} + +SdbWinUsbInterfaceObject::~SdbWinUsbInterfaceObject() { + ATLASSERT(NULL == winusb_handle_); + ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_); +} + +LONG SdbWinUsbInterfaceObject::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + +SDBAPIHANDLE SdbWinUsbInterfaceObject::CreateHandle() { + // Open USB device for this inteface Note that WinUsb API + // requires the handle to be opened for overlapped I/O. + usb_device_handle_ = CreateFile(interface_name().c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == usb_device_handle_) + return NULL; + + // Initialize WinUSB API for this interface + if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_)) + return NULL; + + // Cache current interface number that will be used in + // WinUsb_Xxx calls performed on this interface. + if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_)) + return false; + + // Cache interface properties + unsigned long bytes_written; + + // Cache USB device descriptor + if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, + reinterpret_cast<PUCHAR>(&usb_device_descriptor_), + sizeof(usb_device_descriptor_), &bytes_written)) { + return false; + } + + // Cache USB configuration descriptor + if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE, + 0, 0, + reinterpret_cast<PUCHAR>(&usb_config_descriptor_), + sizeof(usb_config_descriptor_), &bytes_written)) { + return false; + } + + // Cache USB interface descriptor + if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(), + &usb_interface_descriptor_)) { + return false; + } + + // Save indexes and IDs for bulk read / write endpoints. We will use them to + // convert SDB_QUERY_BULK_WRITE_ENDPOINT_INDEX and + // SDB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs. + for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints; + endpoint++) { + // Get endpoint information + WINUSB_PIPE_INFORMATION pipe_info; + if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint, + &pipe_info)) { + return false; + } + + if (UsbdPipeTypeBulk == pipe_info.PipeType) { + // This is a bulk endpoint. Cache its index and ID. + if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) { + // Use this endpoint as default bulk read endpoint + ATLASSERT(0xFF == def_read_endpoint_); + def_read_endpoint_ = endpoint; + read_endpoint_id_ = pipe_info.PipeId; + } else { + // Use this endpoint as default bulk write endpoint + ATLASSERT(0xFF == def_write_endpoint_); + def_write_endpoint_ = endpoint; + write_endpoint_id_ = pipe_info.PipeId; + } + } + } + + return SdbInterfaceObject::CreateHandle(); +} + +bool SdbWinUsbInterfaceObject::CloseHandle() { + if (NULL != winusb_handle_) { + WinUsb_Free(winusb_handle_); + winusb_handle_ = NULL; + } + if (INVALID_HANDLE_VALUE != usb_device_handle_) { + ::CloseHandle(usb_device_handle_); + usb_device_handle_ = INVALID_HANDLE_VALUE; + } + + return SdbInterfaceObject::CloseHandle(); +} + +bool SdbWinUsbInterfaceObject::GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + if (NULL == buffer_char_size) { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Calculate serial number string size. Note that WinUsb_GetDescriptor + // API will not return number of bytes needed to store serial number + // string. So we will have to start with a reasonably large preallocated + // buffer and then loop through WinUsb_GetDescriptor calls, doubling up + // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned. + union { + // Preallocate reasonably sized buffer on the stack. + char small_buffer[64]; + USB_STRING_DESCRIPTOR initial_ser_num; + }; + USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num; + // Buffer byte size + unsigned long ser_num_size = sizeof(small_buffer); + // After successful call to WinUsb_GetDescriptor will contain serial + // number descriptor size. + unsigned long bytes_written; + while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE, + usb_device_descriptor_.iSerialNumber, + 0x0409, // English (US) + reinterpret_cast<PUCHAR>(ser_num), + ser_num_size, &bytes_written)) { + // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here. + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast<char*>(ser_num); + return false; + } + + // Double up buffer size and reallocate string buffer + ser_num_size *= 2; + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast<char*>(ser_num); + try { + ser_num = + reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]); + } catch (...) { + SetLastError(ERROR_OUTOFMEMORY); + return false; + } + } + + // Serial number string length + unsigned long str_len = (ser_num->bLength - + FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / + sizeof(wchar_t); + + // Lets see if requested buffer is big enough to fit the string + if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) { + // Requested buffer is too small. + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast<char*>(ser_num); + *buffer_char_size = str_len + 1; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return false; + } + + bool ret = true; + if (ansi) { + // We need to convert name from wide char to ansi string + if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString, + static_cast<int>(str_len), + reinterpret_cast<PSTR>(buffer), + static_cast<int>(*buffer_char_size), + NULL, NULL)) { + // Zero-terminate output string. + reinterpret_cast<char*>(buffer)[str_len] = '\0'; + } else { + ret = false; + } + } else { + // For wide char output just copy string buffer, + // and zero-terminate output string. + CopyMemory(buffer, ser_num->bString, bytes_written); + reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0'; + } + + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast<char*>(ser_num); + + return ret; +} + +bool SdbWinUsbInterfaceObject::GetEndpointInformation( + UCHAR endpoint_index, + SdbEndpointInformation* info) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + if (NULL == info) { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Get actual endpoint index for predefined read / write endpoints. + if (SDB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) { + endpoint_index = def_read_endpoint_; + } else if (SDB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) { + endpoint_index = def_write_endpoint_; + } + + // Query endpoint information + WINUSB_PIPE_INFORMATION pipe_info; + if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index, + &pipe_info)) { + return false; + } + + // Save endpoint information into output. + info->max_packet_size = pipe_info.MaximumPacketSize; + info->max_transfer_size = 0xFFFFFFFF; + info->endpoint_address = pipe_info.PipeId; + info->polling_interval = pipe_info.Interval; + info->setting_index = interface_number(); + switch (pipe_info.PipeType) { + case UsbdPipeTypeControl: + info->endpoint_type = SdbEndpointTypeControl; + break; + + case UsbdPipeTypeIsochronous: + info->endpoint_type = SdbEndpointTypeIsochronous; + break; + + case UsbdPipeTypeBulk: + info->endpoint_type = SdbEndpointTypeBulk; + break; + + case UsbdPipeTypeInterrupt: + info->endpoint_type = SdbEndpointTypeInterrupt; + break; + + default: + info->endpoint_type = SdbEndpointTypeInvalid; + break; + } + + return true; +} + +SDBAPIHANDLE SdbWinUsbInterfaceObject::OpenEndpoint( + UCHAR endpoint_index, + SdbOpenAccessType access_type, + SdbOpenSharingMode sharing_mode) { + // Convert index into id + UCHAR endpoint_id; + + if ((SDB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) || + (def_read_endpoint_ == endpoint_index)) { + endpoint_id = read_endpoint_id_; + endpoint_index = def_read_endpoint_; + } else if ((SDB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) || + (def_write_endpoint_ == endpoint_index)) { + endpoint_id = write_endpoint_id_; + endpoint_index = def_write_endpoint_; + } else { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + return OpenEndpoint(endpoint_id, endpoint_index); +} + +SDBAPIHANDLE SdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id, + UCHAR endpoint_index) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + SdbEndpointObject* sdb_endpoint = NULL; + + try { + sdb_endpoint = + new SdbWinUsbEndpointObject(this, endpoint_id, endpoint_index); + } catch (...) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + SDBAPIHANDLE ret = sdb_endpoint->CreateHandle(); + + sdb_endpoint->Release(); + + return ret; +} diff --git a/src/sdbwinusbapi/sdb_winusb_interface.h b/src/sdbwinusbapi/sdb_winusb_interface.h new file mode 100644 index 0000000..6a37996 --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_interface.h @@ -0,0 +1,205 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_SDB_WINUSB_INTERFACE_H__ +#define ANDROID_USB_API_SDB_WINUSB_INTERFACE_H__ +/** \file + This file consists of declaration of class SdbWinUsbInterfaceObject + that encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ + +#include "..\sdbwinapi\sdb_interface.h" + +/** \brief Encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ +class SdbWinUsbInterfaceObject : public SdbInterfaceObject { + public: + /** \brief Constructs the object. + + @param[in] interf_name Name of the interface + */ + explicit SdbWinUsbInterfaceObject(const wchar_t* interf_name); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~SdbWinUsbInterfaceObject(); + + // + // Virtual overrides + // + + public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of SdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of SdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + + /** \brief Creates handle to this object. + + In this call a handle for this object is generated and object is added + to the SdbObjectHandleMap. We override this method in order to initialize + WinUsb API for the given interface. + @return A handle to this object on success or NULL on an error. + If NULL is returned GetLastError() provides extended error + information. ERROR_GEN_FAILURE is set if an attempt was + made to create already opened object. + */ + virtual SDBAPIHANDLE CreateHandle(); + + /** \brief This method is called when handle to this object gets closed. + + In this call object is deleted from the SdbObjectHandleMap. We override + this method in order close WinUsb handle created in CreateHandle method + of this class. + @return true on success or false if object is already closed. If + false is returned GetLastError() provides extended error + information. + */ + virtual bool CloseHandle(); + + // + // Abstract overrides + // + + public: + /** \brief Gets serial number for interface's device. + + @param[out] buffer Buffer for the serail number string. Can be NULL in + which case buffer_char_size will contain number of characters + required for the string. + @param[in,out] buffer_char_size On the way in supplies size (in characters) + of the buffer. On the way out, if method failed and GetLastError + reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters + required for the name. + @param[in] ansi If true the name will be returned as single character + string. Otherwise name will be returned as wide character string. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi); + + /** \brief Gets information about an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: SDB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and SDB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[out] info Upon successful completion will have endpoint information. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetEndpointInformation(UCHAR endpoint_index, + SdbEndpointInformation* info); + + /** \brief Opens an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: SDB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and SDB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[in] access_type Desired access type. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always read / write access. + @param[in] sharing_mode Desired share mode. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always shared for read / write. + @return Handle to the opened endpoint object or NULL on failure. + If NULL is returned GetLastError() provides extended information + about the error that occurred. + */ + virtual SDBAPIHANDLE OpenEndpoint(UCHAR endpoint_index, + SdbOpenAccessType access_type, + SdbOpenSharingMode sharing_mode); + + // + // Operations + // + + protected: + /** \brief Opens an endpoint on this interface. + + @param[in] endpoint_id Endpoint (pipe) address on the device. + @param[in] endpoint_index Zero-based endpoint index. + @return Handle to the opened endpoint object or NULL on failure. + If NULL is returned GetLastError() provides extended information + about the error that occurred. + */ + SDBAPIHANDLE OpenEndpoint(UCHAR endpoint_id, UCHAR endpoint_index); + + public: + /// Gets handle to the USB device + HANDLE usb_device_handle() const { + return usb_device_handle_; + } + + /// Gets interface handle used by WinUSB API + WINUSB_INTERFACE_HANDLE winusb_handle() const { + return winusb_handle_; + } + + /// Gets current interface number. + UCHAR interface_number() const { + return interface_number_; + } + + protected: + /// Handle to the USB device + HANDLE usb_device_handle_; + + /// Interface handle used by WinUSB API + WINUSB_INTERFACE_HANDLE winusb_handle_; + + /// Current interface number. This value is obtained via call to + /// WinUsb_GetCurrentAlternateSetting and is used in WinUsb_Xxx + /// calls that require interface number. + UCHAR interface_number_; + + /// Index for the default bulk read endpoint + UCHAR def_read_endpoint_; + + /// ID for the default bulk read endpoint + UCHAR read_endpoint_id_; + + /// Index for the default bulk write endpoint + UCHAR def_write_endpoint_; + + /// ID for the default bulk write endpoint + UCHAR write_endpoint_id_; +}; + +#endif // ANDROID_USB_API_SDB_WINUSB_INTERFACE_H__ diff --git a/src/sdbwinusbapi/sdb_winusb_io_completion.cpp b/src/sdbwinusbapi/sdb_winusb_io_completion.cpp new file mode 100644 index 0000000..283f689 --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_io_completion.cpp @@ -0,0 +1,98 @@ +/* + * 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 SdbWinUsbIOCompletion that + encapsulates a wrapper around OVERLAPPED Win32 structure returned from + asynchronous I/O requests issued via WinUsb API. +*/ + +#include "stdafx.h" +#include "sdb_winusb_io_completion.h" + +SdbWinUsbIOCompletion::SdbWinUsbIOCompletion( + SdbWinUsbEndpointObject* parent_io_obj, + ULONG expected_trans_size, + HANDLE event_hndl) + : SdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl) { +} + +SdbWinUsbIOCompletion::~SdbWinUsbIOCompletion() { +} + +LONG SdbWinUsbIOCompletion::Release() { + ATLASSERT(ref_count_ > 0); + LONG ret = InterlockedDecrement(&ref_count_); + ATLASSERT(ret >= 0); + if (0 == ret) { + LastReferenceReleased(); + delete this; + } + return ret; +} + +bool SdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data, + ULONG* bytes_transferred, + bool wait) { + if (NULL != bytes_transferred) { + *bytes_transferred = 0; + } + + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + ULONG transfer; + bool ret = WinUsb_GetOverlappedResult( + parent_winusb_io_object()->winusb_handle(), + overlapped(), + &transfer, + wait ? TRUE : FALSE) ? true : false; + + // TODO: This is bizzare but I've seen it happening + // that GetOverlappedResult with wait set to true returns "prematurely", + // with wrong transferred bytes value and GetLastError reporting + // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop! + ULONG error = GetLastError(); + + if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) && + ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) { + for (int trying = 0; trying < 10; trying++) { + Sleep(2); + ret = WinUsb_GetOverlappedResult( + parent_winusb_io_object()->winusb_handle(), + overlapped(), + &transfer, + wait ? TRUE : FALSE) ? true : false; + error = GetLastError(); + if (!ret || (0 != transfer) || + ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) { + break; + } + } + } + + if (NULL != ovl_data) { + CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED)); + } + + if (NULL != bytes_transferred) { + *bytes_transferred = transfer; + } + + return ret; +} diff --git a/src/sdbwinusbapi/sdb_winusb_io_completion.h b/src/sdbwinusbapi/sdb_winusb_io_completion.h new file mode 100644 index 0000000..e75a7b2 --- /dev/null +++ b/src/sdbwinusbapi/sdb_winusb_io_completion.h @@ -0,0 +1,118 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_SDB_WINUSB_IO_COMPLETION_H__ +#define ANDROID_USB_API_SDB_WINUSB_IO_COMPLETION_H__ +/** \file + This file consists of declaration of class SdbWinUsbIOCompletion that + encapsulates a wrapper around OVERLAPPED Win32 structure returned from + asynchronous I/O requests issued via WinUsb API. +*/ + +#include "..\sdbwinapi\sdb_io_completion.h" +#include "sdb_winusb_endpoint_object.h" + +/** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32 + structure returned from asynchronous I/O requests issued via WinUsb API. + + A handle to this object is returned to the caller of each successful + asynchronous I/O request. Just like all other handles this handle + must be closed after it's no longer needed. +*/ +class SdbWinUsbIOCompletion : public SdbIOCompletion { + public: + /** \brief Constructs the object + + @param[in] parent_io_obj Parent WinUsb I/O object that created this + instance. + @param[in] expected_trans_size Number of bytes expected to be transferred + with the I/O. + @param[in] event_hndl Event handle that should be signaled when I/O + completes. Can be NULL. If it's not NULL this handle will be + used to initialize OVERLAPPED structure for this object. + */ + SdbWinUsbIOCompletion(SdbWinUsbEndpointObject* parent_io_obj, + ULONG expected_trans_size, + HANDLE event_hndl); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~SdbWinUsbIOCompletion(); + + // + // Virtual overrides + // + + public: + /** \brief Releases the object. + + If refcount drops to zero as the result of this release, the object is + destroyed in this method. As a general rule, objects must not be touched + after this method returns even if returned value is not zero. We override + this method in order to make sure that objects of this class are deleted + in contect of the DLL they were created in. The problem is that since + objects of this class were created in context of SdbWinUsbApi module, they + are allocated from the heap assigned to that module. Now, if these objects + are deleted outside of SdbWinUsbApi module, this will lead to the heap + corruption in the module that deleted these objects. Since all objects of + this class are deleted in the Release method only, by overriding it we make + sure that we free memory in the context of the module where it was + allocated. + @return Value of the reference counter after object is released in this + method. + */ + virtual LONG Release(); + + // + // Abstract overrides + // + + public: + /** \brief Gets overlapped I/O result + + This method uses WinUsb_GetOverlappedResult to get results of the + overlapped I/O operation. + @param[out] ovl_data Buffer for the copy of this object's OVERLAPPED + structure. Can be NULL. + @param[out] bytes_transferred Pointer to a variable that receives the + number of bytes that were actually transferred by a read or write + operation. See SDK doc on GetOvelappedResult for more information. + Unlike regular GetOvelappedResult call this parameter can be NULL. + @param[in] wait If this parameter is true, the method does not return + until the operation has been completed. If this parameter is false + and the operation is still pending, the method returns false and + the GetLastError function returns ERROR_IO_INCOMPLETE. + @return true if I/O has been completed or false on failure or if request + is not yet completed. If false is returned GetLastError() provides + extended error information. If GetLastError returns + ERROR_IO_INCOMPLETE it means that I/O is not yet completed. + */ + virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data, + ULONG* bytes_transferred, + bool wait); + + public: + /// Gets WinUsb parent object + SdbWinUsbEndpointObject* parent_winusb_io_object() const { + return reinterpret_cast<SdbWinUsbEndpointObject*>(parent_io_object()); + } +}; + +#endif // ANDROID_USB_API_SDB_WINUSB_IO_COMPLETION_H__ diff --git a/src/sdbwinusbapi/stdafx.cpp b/src/sdbwinusbapi/stdafx.cpp new file mode 100644 index 0000000..83c6e13 --- /dev/null +++ b/src/sdbwinusbapi/stdafx.cpp @@ -0,0 +1,21 @@ +/* + * 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. + */ + +// stdafx.cpp : source file that includes just the standard includes +// SdbWinUsbApi.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/src/sdbwinusbapi/stdafx.h b/src/sdbwinusbapi/stdafx.h new file mode 100644 index 0000000..88cd963 --- /dev/null +++ b/src/sdbwinusbapi/stdafx.h @@ -0,0 +1,78 @@ +/* + * 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 + Visual Studio generated include file for standard system include files, or + project specific include files that are used frequently, but are changed + infrequently. +*/ + +#pragma once + +#ifndef STRICT +#define STRICT +#endif + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later. +#define WINVER 0x0500 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later. +#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target Windows 2000 or later. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0500 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later. +#define _WIN32_IE 0x0501 // Change this to the appropriate value to target IE 5.0 or later. +#endif + +// These defines prevent the MS header files from ejecting #pragma comment +// statements with the manifest information of the used ATL, STL, and CRT +#define _ATL_NOFORCE_MANIFEST +#define _STL_NOFORCE_MANIFEST +#define _CRT_NOFORCE_MANIFEST + +#define _ATL_APARTMENT_THREADED +#define _ATL_NO_AUTOMATIC_NAMESPACE + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +// turns off ATL's hiding of some common and often safely ignored warning messages +#define _ATL_ALL_WARNINGS + +// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include <windows.h> +#pragma warning(disable: 4702) +#pragma warning(disable: 4201) +#include <atlbase.h> +#include <winioctl.h> +#include <setupapi.h> +#include <vector> +#include <map> +#include <string> +#pragma warning(default: 4201) +#pragma warning(disable: 4200) +#include <winusb.h> + +#include "resource.h" + +using namespace ATL; |